2011-06-10 74 views
16

爲什麼在調用pthread_cond_wait之前需要鎖定互斥鎖?pthread_cond_wait和互斥要求

此外,在撥打pthread_cond_signal之前是否需要鎖定(在同一個互斥體上)?

感謝您的幫助。

+2

另請參閱:http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex – ninjalj 2011-06-10 22:26:34

回答

25

爲什麼在調用pthread_cond_wait之前需要鎖定互斥鎖?

因爲否則就有不可避免的競爭條件。

互斥鎖保護共享狀態。條件變量與狀態上的某個謂詞(「條件」)相關聯。其基本思想是要:

1)檢查謂詞

2)如果斷言是假的,去睡覺,直到它變成真正的

在併發系統中,總是有可能(1)和(2)之間的謂詞爲真。爲避免這種競爭,您必須在(1)之前持有一個互斥體,並且您必須在執行(2)時自動釋放它。

例如,對於一個隊列,謂詞可能是「隊列不是空的」。但是,在檢查隊列是否非空以及休眠的時間之間,其他一些線程可能會將某些內容添加到隊列中。

因此,您必須在檢查謂詞和調用pthread_cond_wait時同時持有互斥鎖。

此外,在調用pthread_cond_signal之前是否需要鎖定(在同一個互斥鎖上)?

據我所知,這沒有根本的問題;它只是引入潛在的低效率。

在這裏再一次,無論您正在修改共享狀態(從而使謂詞爲真)必須受互斥體保護。因此,無論如何,只要想要發出信號,您必須已經持有該互斥量。

如果在發送條件信號之前釋放互斥鎖,則由於某個其他線程的操作,謂詞之間可能變爲false。這場比賽不會導致失敗,因爲任何等待條件的線程在進行之前都必須仔細檢查謂詞......但爲什麼要通過這個麻煩呢?

底線:只要按照說明操作,您甚至不必考慮這些問題。 :-)

+0

+1瞭解詳細的答案。 :-)我認爲需要鎖定信號是爲了確保內存一致性,因爲鎖定互斥鎖涉及內存屏障。沒有它,其他線程可能無法觀察到變化。 (雖然,我猜可能有內存屏蔽信號,但是,需要一個鎖可能更簡單。) – 2011-06-10 21:49:59

+1

@Chris:POSIX需要'pthread_cond _ *()'來同步內存:http:// pubs。 opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_11 – ninjalj 2011-06-10 22:05:26

+0

@ninjalj:啊,非常好。謝謝! :-) – 2011-06-10 22:12:15

1

條件變量用於在您希望更改的條件下進行同步。鎖定確保:

  • 的改變可以在等待的線程可以可靠地觀察到
  • 下變化的項目不以某種方式通過另一個線程同時現已喚醒的線程之一改變時,觀察它

不使用互斥鎖的條件系統會更脆弱。

1

條件變量的要點是允許向線程通知由互斥鎖保護的數據結構上的更改,例如,您可能希望在隊列不再爲空時通知您,因此您可以以原子方式釋放互斥鎖並等待條件變量,並且當新元素排隊時,您將喚醒並使用互斥鎖處理新元素。

與Java的監視器不同,pthread_cond_{signal,broadcast}()不需要保存互斥量。當沒有線程在該條件變量上等待時,發送一個條件變量的信號會丟失,但這不應該產生很大的差別,因爲如果生產者在消費者之前開始運行,信號也可能丟失。