2014-10-31 32 views
3

從我的學習中,我瞭解飢餓,死鎖,公平和其他併發問題的概念。然而,理論從實踐不同,在一定程度上和實際工程任務經常涉及不是學術等等等等更詳細...C++線程與可見性問題 - 常見的工程實踐是什麼?

爲C++開發人員,我一直關注了一段時間線程問題...

假設您有一個共享變量x,它指向程序內存的一部分。該變量在兩個線程AB之間共享。

現在,如果我們考慮從AB線程的x讀取/寫入操作,可能在同一時間,需要同步這些操作,對吧?因此,對x的訪問需要某種形式的同步,例如可以通過使用互斥鎖來實現。

現在讓我們考慮在x最初寫的線程A另一個場景,然後傳遞到線程B(不知)和線程只讀取x。線程B然後產生對x的響應,稱爲y,並將其傳遞迴線程A(再次,以某種方式)。我的問題是:我應該使用什麼同步原語來使這個場景是線程安全的。我讀過關於原子,更重要的是記憶柵欄 - 這些是我應該依賴的工具嗎?

這不是一個典型的情況,其中有一個「關鍵部分」。相反,一些數據在線程之間傳遞,不可能在同一個內存位置同時寫入。所以,在寫入之後,數據首先應該以某種方式「刷新」,以便其他線程在讀取之前能夠以有效和一致的狀態看到它。它是如何被稱爲文學,它是「知名度」?

pthread_once和它的Boost/std對應部分,即call_once。如果xy通過一種「消息隊列」在線程之間傳遞,這是通過「一次」功能訪問的,這會有所幫助嗎? AFAIK它作爲一種記憶圍欄,但我無法找到任何確認。

CPU緩存及其一致性如何?從工程角度我應該知道什麼?這些知識是否有助於上述場景,或者C++開發中經常遇到的其他場景?

我知道我可能會混合很多主題,但我想更好地瞭解什麼是常見的工程實踐,以便我可以重複使用已知的模式。

這個問題主要與C++ 03的情況有關,因爲這是我工作時的日常環境。由於我的項目主要涉及Linux,因此我只能使用pthread和Boost,包括Boost.Atomic。但是,如果關於這些問題的任何事情隨着C++ 11的出現而改變,我也感興趣。

我知道這個問題是抽象的,沒有那麼精確,但任何輸入都可能有用。

+0

對於任何Qt開發人員,你可以使用Qt的信號/槽或事件系統,實現線程安全的消息傳遞。 – 2014-11-01 00:34:57

+0

@Siyuan:同樣是Win32的消息隊列和其他人的真實...但這些(包括Qt)是用戶界面,而不是通用的應用進行了優化。 – 2014-11-01 01:07:54

回答

10

你有一個共享變量x

這就是你出了錯。如果您使用某種線程安全的消費者 - 生產者隊列來移交工作項目的所有權,並且從程序其餘部分(包括所有業務邏輯)的角度來看,線程更容易分配,任何事情都不會共享。

消息傳遞也有助於防止緩存衝突(因爲沒有真正的共享 - 除了生產者 - 消費者隊列本身,並且如果工作單元很大,對性能的影響微乎其微 - 並且將數據組織到消息有助於減少錯誤分享)。

並行當你分開的問題劃分爲若干子秤最好的。小的子問題也更容易推理。

你似乎已經沿着這些路線思考,但沒有,線程原語像原子公司,互斥和圍欄都沒有使用消息傳遞應用非常好。找到一個真正的隊列實現(隊列,圓環,Disruptor,它們使用不同的名字,但都滿足相同的需求)。原語將在隊列實現中使用,但從不會由應用程序代碼使用。