2017-07-30 19 views
1

示例: 線程完成寫入共享變量的操作,然後解鎖它,但繼續使用該變量的值(而不更改它)。 然後,另一個線程立即成功解鎖()該互斥並讀取共享變量。PTHREAD互斥體只能避免同時訪問資源,或者它還有其他更多的功能嗎?

對於我的(誤)的理解,有些事情可能會發生在這種情況:

在寫線程:

  • 編譯器優化可以使寫僅發生在稍後的某個點

  • 寫入的值可以保留在當前CPU核心的緩存,並刷新到內存在以後的某個點

在讀線程:

  • 可以互斥鎖()之前已經被讀取變量的值,因爲一些編譯器優化或只是CPU緩存平時的工作中,依然是認爲「已經從內存中讀取」,因此不會再從內存中取回。

  • 因此,我們這裏的值不是來自其他線程的更新值。

是否並行線程互斥鎖定/解鎖()函數執行任何代碼,以「刷新」當前緩存到內存和其他任何以確保當前線程需要的是一切同步(我想不出除了緩存以外的其他東西),還是僅僅不需要(至少在所有已知的架構中)?因爲如果所有的互斥量都是這個名稱的作用 - 互斥對它的引用 - 那麼,如果我有成千上萬的線程處理相同的數據,並且從我的算法的角度來看,我已經知道當一個互斥量線程正在使用變量,沒有其他線程會嘗試同時使用它,這意味着我不需要互斥鎖?或者我的代碼是否會缺少PTHREAD庫中實現的一些低級別和特定於架構的方法以避免上述問題?

回答

2

pthreads互斥鎖定和解鎖函數是POSIX 「...中的函數列表」,它們可以同步線程的執行並且還可以使內存與其他線程同步「。所以是的,他們做的不僅僅是聯鎖執行。

不管他們是否需要發出更多的指令,硬件當然是架構的依賴(注意,幾乎每一個現代的CPU架構將至少愉快地重新排序相對於相互讀取,除非另行告知),但在每一個這些函數必須充當「編譯器障礙」 - 也就是說,它們確保編譯器不會在允許的情況下重新排序,合併或省略內存訪問。

允許多線程讀取共享值而不會互斥 - 但您需要確保寫入和讀取線程在寫入和讀取之間執行了一些同步功能。例如,允許的情況是有多個讀取線程推遲讀取共享狀態,直到它們通過障礙(pthread_barrier_wait()),並且寫入線程在通過障礙之前將其所有寫入寫入共享狀態。讀寫器鎖(pthread_rwlock_*)也是圍繞這個想法構建的。