程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> pthread_mutex_lock()的屬性介紹

pthread_mutex_lock()的屬性介紹

編輯:C++入門知識

pthread_mutex_lock()的屬性介紹


pthread_mutex_lock

pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

描述 pthread_mutex_lock()函數鎖住由mutex指定的mutex 對象。如果mutex已經被鎖住,調用這個函數的線程阻塞直到mutex可用為止。這跟函數返回的時候參數mutex指定的mutex對象變成鎖住狀態, 同時該函數的調用線程成為該mutex對象的擁有者。

如果mutex 對象的type是 PTHREAD_MUTEX_NORMAL,不進行deadlock detection(死鎖檢測)。企圖進行relock 這個mutex會導致deadlock. 如果一個線程對未加鎖的或已經unlock的mutex對象進行unlock操作,結果是不未知的。

如果mutex類型是 PTHREAD_MUTEX_ERRORCHECK,那麼將進行錯誤檢查。如果一個線程企圖對一個已經鎖住的mutex進行relock,將返回一個錯 誤。如果一個線程對未加鎖的或已經unlock的mutex對象進行unlock操作,將返回一個錯誤。

如果mutex類型是 PTHREAD_MUTEX_RECURSIVE,mutex會有一個鎖住次數(lock count)的概念。當一個線程成功地第一次鎖住一個mutex的時候,鎖住次數(lock count)被設置為1,每一次一個線程unlock這個mutex的時候,鎖住次數(lock count)就減1。當鎖住次數(lock count)減少為0的時候,其他線程就能獲得該mutex鎖了。如果一個線程對未加鎖的或已經unlock的mutex對象進行unlock操作,將返 回一個錯誤。

如果mutex類型是 PTHREAD_MUTEX_DEFAULT,企圖遞歸的獲取這個mutex的鎖的結果是不確定的。unlock一個不是被調用線程鎖住的mutex的結 果也是不確定的。企圖unlock一個未被鎖住的mutex導致不確定的結果。

pthread_mutex_trylock()調用在參數mutex指定的mutex對象當前被鎖住的時候立即返回,除此之外,pthread_mutex_trylock()跟pthread_mutex_lock()功能完全一樣。

pthread_mutex_unlock()函數釋放有參數mutex指定的mutex對象的鎖。如果被釋放取決於該Mutex對象的類型屬性。如果有多個線程為了獲得該mutex鎖阻塞,調用pthread_mutex_unlock()將是該mutex可用,一定的調度策略將被用來決定哪個線程可以獲得該mutex鎖。(在mutex類型為PTHREAD_MUTEX_RECURSIVE 的情況下,只有當lock count 減為0並且調用線程在該mutex上已經沒有鎖的時候)(翻譯到這裡,才覺得我的這個鎖概念是多麼模糊) 如果一個線程在等待一個mutex鎖得時候收到了一個signal,那麼在從signal handler返回的時候,該線程繼續等待該mutex鎖,就像這個線程沒有被中斷一樣。

返回值成功

pthread_mutex_lock() 和 pthread_mutex_unlock() 返回0,否則返回一個錯誤的提示碼

pthread_mutex_trylock() 在成功獲得了一個mutex的鎖後返回0,否則返回一個錯誤提示碼錯誤

pthread_mutex_lock() 和 pthread_mutex_unlock()失敗的時候 [EINVAL] mutex在生成的時候,它的protocol屬性的值是 PTHREAD_PRIO_PROTECT,同時調用線程的優先級(priority)比該mutex的當前prority上限高

pthread_mutex_trylock() 函數在一下情況會失敗:

[EBUSY] The mutex could not be acquired because it was already locked. mutex已經被鎖住的時候無法再獲取鎖

The pthread_mutex_lock(), pthread_mutex_trylock() and pthread_mutex_unlock() functions may fail if:

[EINVAL] mutex指向的mutex未被初始化

[EAGAIN] Mutex的lock count(鎖數量)已經超過 遞歸索的最大值,無法再獲得該mutex鎖

pthread_mutex_lock() 函數在一下情況下會失敗:

[EDEADLK] 當前線程已經獲得該mutex鎖

pthread_mutex_unlock() 函數在以下情況下會失敗:

[EPERM] 當前線程不是該mutex鎖的擁有者 所有的這些函數的錯誤返回值都不會是[EINTR]

互斥鎖

互斥鎖用來保證一段時間內只有一個線程在執行一段代碼。必要性顯而易見:假設各個線程向同一個文件順序寫入數據,最後得到的結果一定是災難性的。

我們先看下面一段代碼。這是一個讀/寫程序,它們公用一個緩沖區,並且我們假定一個緩沖區只能保存一條信息。即緩沖區只有兩個狀態:有信息或沒有信息。

void reader_function ( void );
void writer_function ( void );

char buffer;
int buffer_has_item=0;
pthread_mutex_t mutex;
struct timespec delay;
void main ( void ){
pthread_t reader;
/* 定義延遲時間*/
delay.tv_sec = 2;
delay.tv_nec = 0;
/* 用默認屬性初始化一個互斥鎖對象*/
pthread_mutex_init (&mutex,NULL);
pthread_create(&reader, pthread_attr_default, (void *)&reader_function), NULL);
writer_function( );
}

void writer_function (void){
while(1){
/* 鎖定互斥鎖*/
pthread_mutex_lock (&mutex);
if (buffer_has_item==0){
buffer=make_new_item( );
buffer_has_item=1;
}
/* 打開互斥鎖*/
pthread_mutex_unlock(&mutex);
pthread_delay_np(&delay);
}
}

void reader_function(void){
while(1){
pthread_mutex_lock(&mutex);
if(buffer_has_item==1){
consume_item(buffer);
buffer_has_item=0;
}
pthread_mutex_unlock(&mutex);
pthread_delay_np(&delay);
}
}


這裡聲明了互斥鎖變量mutex,結構pthread_mutex_t為不公開的數據類型,其中包含一個系統分配的屬性對象。函數 pthread_mutex_init用來生成一個互斥鎖。NULL參數表明使用默認屬性。如果需要聲明特定屬性的互斥鎖,須調用函數 pthread_mutexattr_init。函數pthread_mutexattr_setpshared和函數 pthread_mutexattr_settype用來設置互斥鎖屬性。前一個函數設置屬性pshared,它有兩個取 值,PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。前者用來不同進程中的線程同步,後者用於同步本進 程的不同線程。在上面的例子中,我們使用的是默認屬性PTHREAD_PROCESS_ PRIVATE。後者用來設置互斥鎖類型,可選的類型有PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、 PTHREAD_MUTEX_RECURSIVE和PTHREAD _MUTEX_DEFAULT。它們分別定義了不同的上所、解鎖機制,一般情況下,選用最後一個默認屬性。

pthread_mutex_lock聲明開始用互斥鎖上鎖,此後的代碼直至調用pthread_mutex_unlock為止,均被上鎖,即同一時間只 能被一個線程調用執行。當一個線程執行到pthread_mutex_lock處時,如果該鎖此時被另一個線程使用,那此線程被阻塞,即程序將等待到另一 個線程釋放此互斥鎖。在上面的例子中,我們使用了pthread_delay_np函數,讓線程睡眠一段時間,就是為了防止一個線程始終占據此函數。

上面的例子非常簡單,就不再介紹了,需要提出的是在使用互斥鎖的過程中很有可能會出現死鎖:兩個線程試圖同時占用兩個資源,並按不同的次序鎖定相應的互 斥鎖,例如兩個線程都需要鎖定互斥鎖1和互斥鎖2,a線程先鎖定互斥鎖1,b線程先鎖定互斥鎖2,這時就出現了死鎖。此時我們可以使用函數 pthread_mutex_trylock,它是函數pthread_mutex_lock的非阻塞版本,當它發現死鎖不可避免時,它會返回相應的信 息,程序員可以針對死鎖做出相應的處理。另外不同的互斥鎖類型對死鎖的處理不一樣,但最主要的還是要程序員自己在程序設計注意這一點。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved