2010-06-15 111 views
2

我遇到了一個互斥鎖問題(Linux上的pthread_mutex),如果一個線程在解鎖後再次鎖定一個互斥鎖,另一個線程並不會非常成功地獲得一個鎖。我附加了創建一個互斥體的測試代碼,以及兩個在無限循環中鎖定互斥體的線程,睡眠一段時間並再次解鎖。永久互斥鎖造成死鎖?

我期望看到的輸出是來自兩個線程的「活動」消息,每個線程都有一個(例如121212121212)。但是我得到的結果是一個線程獲取大部分鎖(例如111111222222222111111111或僅1111111111111 ...)。

如果我在解鎖後添加一個usleep(1),一切都按預期工作。顯然,當線程進入SLEEP時,另一個線程獲取鎖 - 但這不是我期待的方式,因爲另一個線程已經調用了pthread_mutex_lock,我懷疑這是實現的方式,因爲actice線程具有優先級,但是它在這個特定的測試用例中會導致某些問題。是否有任何方法來防止它(僅僅添加一個故意足夠大的延遲或某種信號)或我的錯誤在哪裏理解?

#include <pthread.h> 
#include <stdio.h> 

#include <string.h> 
#include <sys/time.h> 
#include <unistd.h> 

pthread_mutex_t mutex; 

void* threadFunction(void *id) { 
int count=0; 

while(true) { 
    pthread_mutex_lock(&mutex); 
    usleep(50*1000); 
    pthread_mutex_unlock(&mutex); 
    // usleep(1); 

    ++count; 
    if (count % 10 == 0) { 
    printf("Thread %d alive\n", *(int*)id); 
    count = 0; 
    } 
} 

return 0; 
} 

int main() { 
// create one mutex 
pthread_mutexattr_t attr; 
pthread_mutexattr_init(&attr); 
pthread_mutex_init(&mutex, &attr); 

// create two threads 
pthread_t thread1; 
pthread_t thread2; 

pthread_attr_t attributes; 
pthread_attr_init(&attributes); 

int id1 = 1, id2 = 2; 
pthread_create(&thread1, &attributes, &threadFunction, &id1); 
pthread_create(&thread2, &attributes, &threadFunction, &id2); 

pthread_attr_destroy(&attributes); 

sleep(1000); 
return 0; 
} 

回答

2

您誤解了互斥鎖的工作方式(至少在您的特定實現情況下)。互斥體的釋放不會自動切換到正在等待它的另一個線程。

通常,線程一直運行,直到他們不得不等待資源或他們用完量子(時間片)。

如果沒有資源爭用,並且所有線程具有相同的優先級,最公平的調度算法是在交換之前爲每個時間片賦予相同的時間片。這是因爲交換操作本身需要一些時間,所以你不想過於頻繁(相對於線程所做的實際工作而言)。

如果你想在線程之間交替,你需要一些更確定的比如一組條件變量:

+0

我希望另一個線程的鎖定調用會被註冊並導致當前正在運行的線程的鎖不成功(即排隊的互斥鎖)。由於這是一個人爲設計的測試用例,實際上並沒有出現在我的應用程序中,所以我會放棄它,但如果此問題再次出現,請記住您的答案。 – Daniel 2010-06-15 13:08:39

1

這不是死鎖,它甚至不是死鎖,它僅僅是缺少公平性如果這對你很重要,你應該使用基元確保非飢餓,例如排隊互斥鎖

0

當第一個線程解鎖互斥鎖時,當然會有一些延遲,然後該更改是ava適用於其他線程。這可能比第一個線程重新鎖定互斥鎖的時間要長,因爲它不必等待這個時間。