我讀到APUE 3rd,11.6.1互斥,存在關於鎖定一個例子,在本章中解鎖互斥:如何在Linux中使用pthread_mutex_destroy安全並正確地銷燬互斥鎖?
struct foo {
int f_count;
pthread_mutex_t f_lock;
int f_id;
/* ... more stuff here ... */
};
struct foo *
foo_alloc(int id) /* allocate the object */
{
struct foo *fp;
if ((fp = malloc(sizeof(struct foo))) != NULL) {
fp->f_count = 1;
fp->f_id = id;
if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
free(fp);
return(NULL);
}
/* ... continue initialization ... */
}
return(fp);
}
void
foo_hold(struct foo *fp) /* add a reference to the object */
{
pthread_mutex_lock(&fp->f_lock);
fp->f_count++;
pthread_mutex_unlock(&fp->f_lock);
}
void
foo_rele(struct foo *fp) /* release a reference to the object */
{
pthread_mutex_lock(&fp->f_lock);
if (--fp->f_count == 0) { /* last reference */
pthread_mutex_unlock(&fp->f_lock);
pthread_mutex_destroy(&fp->f_lock);
free(fp);
} else {
pthread_mutex_unlock(&fp->f_lock);
}
}
在foo_rele,有調用pthread_mutex_unlock和pthread_mutex_destroy之間的競爭條件,所以,乙線程可以調用pthread_mutex_unlock和pthread_mutex_destroy之間的pthread_mutex_lock在線程這將導致未定義的行爲(試圖銷燬鎖定的互斥鎖導致未定義的行爲)。我對嗎?如果我是對的,那麼,如何使它正常工作,或者如何在Linux中使用pthread_mutex_destroy安全並正確地銷燬互斥鎖?
能否請您參考** 11.6.2死鎖避免**檢查示例代碼,我覺得線程只能通過調用'foo_find'增加對象引用,而不是'foo_hold'直接,我說的對? – cong
是的只有'foo_find()'調用'foo_hold()'。當'foo_rele()'發現它要將一個refcount遞減爲0時,它會在持有互斥鎖的同時從哈希表中刪除項目,所以沒有其他線程可以再次獲得指向該'foo'對象的指針。一旦發生這種情況,可以解鎖互斥鎖,'foo'對象中的互斥鎖可以被銷燬,並且'foo'對象本身被釋放,因爲沒有別的東西可以再獲得'foo'對象。 –
**第11.6.2節中的示例代碼有兩個版本,在版本一中,代碼'foo_hold(fp);''foo_find''應替換爲: 'pthread_mutex_lock(&fp-> f_lock) ; fp-> f_count ++; pthread_mutex_unlock(&fp-> f_lock);' 和函數'foo_hold'應該被移除。 在第二版中,功能'foo_hold'應該被移除,另一方面,這是沒有用的和危險的,用戶可能會濫用界面,對吧? – cong