簡體   English   中英

帶線程的 C/C++ 數組 - 我需要使用互斥鎖還是鎖?

[英]C/C++ arrays with threads - do I need to use mutexes or locks?

我是使用線程的新手,並且已經閱讀了很多關於如何共享和保護數據的內容。 但我也沒有真正掌握使用互斥鎖和鎖來保護數據。

下面是我將要解決的問題的描述。 需要注意的重要一點是,這將是時間緊迫的,所以我需要盡可能地減少開銷。

我有兩個固定大小的雙數組。

  • 第一個數組將為后續計算提供數據。 線程將從它讀取值,但它永遠不會被修改。 某個元素可能會在某個時間被任何線程讀取。

  • 第二個數組將用於存儲線程執行的計算結果。 這個數組的一個元素只會被一個線程更新,並且可能只有一次當結果值
    是寫給它的。

我的問題是:

  1. 每次訪問只讀數組中的數據時,我真的需要在線程中使用互斥鎖嗎? 如果是這樣,你能解釋一下原因嗎?

  2. 當線程寫入結果數組時,我是否需要在線程中使用互斥鎖,即使這將是唯一寫入該元素的線程?

  3. 我應該使用原子數據類型嗎,如果我這樣做會不會有任何顯着的時間開銷?

  4. 此類問題的許多答案似乎是 - 不,如果您的變量對齊,則不需要互斥鎖。 我在這個例子中的數組元素會對齊,還是有什么方法可以確保它們對齊?

該代碼將在 64 位 Linux 上實現。 我計划使用 Boost 庫進行多線程處理。

幾天來我一直在仔細考慮這個問題,並在整個網絡上查看,一旦發布,答案和清晰的解釋在幾秒鍾內就回來了。 有一個“接受的答案”,但所有的答案和評論都同樣有幫助。

  1. 每次訪問只讀數組中的數據時,我真的需要在線程中使用互斥鎖嗎? 如果是,你能解釋一下原因嗎?

不會。因為數據永遠不會被修改,所以不會有同步問題。

  1. 當線程寫入結果數組時,我是否需要在線程中使用互斥鎖,即使這將是唯一寫入該元素的線程?

要看。

  1. 如果任何其他線程要讀取該元素,則需要同步。
  2. 如果任何線程可能會修改向量的大小,則需要同步。

在任何情況下,請注意不要由不同的線程大量寫入相鄰的內存位置。 這可能會破壞性能。 參見“虛假共享”。 考慮到,您可能沒有很多內核,因此沒有很多線程,並且您說寫入僅完成一次,但這可能不會成為一個重大問題。

  1. 我應該使用原子數據類型嗎,如果我這樣做會不會有任何重要的時間開銷?

如果您使用鎖(互斥),則不需要原子變量(並且它們確實有開銷)。 如果不需要同步,則不需要原子變量。 如果您需要同步,那么在某些情況下可以使用原子變量來避免鎖定。 在哪些情況下你可以使用原子而不是鎖......我認為這更復雜,超出了這個問題的范圍。

鑒於您在評論中的情況描述,似乎根本不需要同步,因此不需要原子或鎖。

  1. ...在這個例子中我的數組元素是否會對齊,或者有什么方法可以確保它們對齊?

正如 Arvid 所指出的,您可以使用 c++11 中引入的alginas關鍵字請求特定對齊。 在 c++11 之前,您可以求助於編譯器特定的擴展: https : //gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Variable-Attributes.html

在給定的兩個條件下,不需要互斥鎖。 請記住,每次使用互斥鎖(或任何同步構造)都是一種性能開銷。 所以你想盡可能地避免它們(當然不影響正確的代碼)。

  1. 不。不需要互斥體,因為線程只讀取數組。

  2. 不可以。由於每個線程只寫入不同的內存位置,因此不可能出現競爭條件。

  3. 不。這里不需要對對象進行原子訪問。 事實上,使用原子對象可能會對性能產生負面影響,因為它會阻止優化的可能性,例如重新排序操作。

只有在共享資源上的數據被修改時才需要使用鎖。 例如,如果一些線程用於寫入數據而一些用於讀取數據(在這兩種情況下都來自同一資源),那么您只需要在寫入完成時鎖定。 這是為了防止所謂的“種族”。

當您制作在共享資源上操作數據的程序時,谷歌上有很好的種族信息。

你走在正確的軌道上。

1)對於第一個數組(只讀),您不需要為其使用互斥鎖。 由於線程只是讀取而不是更改數據,因此線程無法破壞另一個線程的數據

2)我對這個問題有點困惑。 如果您知道線程 1 只會將元素寫入數組插槽 1,而線程 2 只會寫入數組插槽 2,那么您不需要互斥鎖。 但是我不確定你是如何實現這個屬性的。 如果我的上述陳述不適合您的情況,您肯定需要一個互斥鎖。

3) 鑒於原子的定義:

原子類型是封裝一個值的類型,該值的訪問保證不會引起數據競爭,並且可用於同步不同線程之間的內存訪問。

重點說明,互斥鎖是原子的,這意味着只需要 1 條匯編指令即可獲取/釋放鎖。 如果需要 2 個組裝指令來抓取/釋放鎖,那么鎖就不是線程安全的。 例如,如果線程 1 嘗試獲取鎖並被切換到線程 2,線程 2 將獲取鎖。

使用原子數據類型會減少你的開銷,但不會顯着。

4)我不確定你如何確保你的變量是內襯的。 由於線程可以在您的程序中隨時切換(您的操作系統確定線程何時切換)

希望這可以幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM