2011-06-06 162 views
0

如果我在函數中的兩個不同位置鎖定相同的互斥鎖,並且當一個線程位於其中一個線程中並且第二個線程到達另一個線程時發生上下文切換,它會被封鎖嗎?線程在同一互斥鎖的多個鎖上的行爲

我會試着給出一個簡單的例子,我的意思是,也許它會更清晰。 說我有下面的代碼在一個文件test.c的

int globalVar = 0;  

void testMutex(pthread_mutex_t myMutex) { 
    pthread_mutex_lock(&myMutex); 
    globalVar++; 
    pthread_mutex_unlock(&myMutex); 

    printf("%s \n", "Doing some other stuff here"); 

    pthread_mutex_lock(&myMutex); 
    globalVar--; 
    pthread_mutex_unlock(&myMutex); 
} 

,並在不同的文件main.c中,我有創建兩個線程,thread1thread2,都運行testMutex功能的主要功能。 thread1首先被執行,而在函數的第二部分( - 部分,在printf之後),在mutex被解鎖之前,thread2從函數開始運行。 將thread2能夠執行globalVar++,還是會保持阻止狀態,等待互斥鎖被解鎖?

在此先感謝!

回答

3

簡短回答是「是」。

pthread_mutex_lock documentation使這很清楚:

mutex引用的互斥對象應的pthread_mutex_lock調用被鎖定()。如果互斥鎖已被鎖定,則調用線程應阻塞,直到互斥鎖變爲可用。該操作將返回互斥體對象,該互斥體對象在調用線程作爲其所有者的鎖定狀態下由互斥量引用。

換句話說,從pthread_mutex_lock返回時,互斥量由線程「擁有」。系統保證最多一個線程可以隨時「擁有」一個互斥體。

4

首先,你不應該四處傳遞pthread_mutex_t按值:

void testMutex(pthread_mutex_t myMutex) 

作出這樣的pthread_mutex_t*。即使您的代碼可能爲您工作(我懷疑),它不是可移植的,因爲pthreads類型意味着不透明。

There's a discussion of this in the relevant FAQ。除此之外,它暗示了您使用pthread_mutex_t會導致每次調用testMutex時互斥體的副本(使用鎖定副本而不是原始互斥鎖的功能)的副本。

一旦你解決了這個,下面將舉行:

由於兩個線程都使用相同的互斥體,以塊第二個線程在任意一個pthread_mutex_lock電話,只要第一個線程在兩個pthread_mutex_lock - pthread_mutex_unlock部分的內部。反過來也是如此(只要第二個線程具有互斥體,第一個線程就會阻塞)。

換句話說,只要一個線程對互斥量具有鎖定,其他線程就不能鎖定相同的互斥量。

+0

我不認爲有這個代碼將工作的任何實現。相反,'pthread_mutex_lock'會鎖定一個*互斥鎖的副本,它不會阻塞其他線程。技術上對互斥副本執行任何操作都會導致UB,但行爲幾乎可以肯定地像我剛纔描述的那樣用於實際實現。 – 2011-06-06 19:08:53

+1

其實您鏈接的FAQ中的文本是錯誤的。與它所說的相反,複製'pthread_t'完全有效,事實上,在標準函數中'pthread_t'的所有用法都是通過值(即使它是一個結構)而不是通過引用來傳遞它,除了'pthread_create',其中地址來存儲結果通過。當然,'pthread_t'通常本身就是一個指向不透明數據結構的指針。 – 2011-10-15 04:47:08

1

thread2將阻塞在pthread_mutex_lock()函數中,直到thread1解鎖互斥鎖爲止。

如果沒有,那麼互斥體的目的是什麼呢?

0

線程2將保持阻塞狀態,直到線程1釋放互斥鎖後才能增加globalVarr ++。

0

函數中的位置並不重要 - 如果一個線程有互斥鎖,另一個線程不能獲取它。