簡體   English   中英

線程安全和位域

[英]Thread safety and bit-field

我知道位域依賴於編譯器,但我還沒有找到有關最新 g++ 和 Visual C++ 2010 的位域線程安全的文檔。

對位域成員的操作是原子的嗎?

不幸的是,“線程安全”是編程中一個非常重載的術語。

如果您的意思是對位域的原子訪問,答案是否定的(至少在我知道的所有處理器上)。 您可以原子訪問 32 位機器上的 32 位 memory 位置,但這僅意味着您將讀取或寫入整個 32 位值。 這並不意味着另一個線程不會做同樣的事情。 如果您想停止,您可能需要同步。

如果您的意思是對位域的同步訪問,答案也是否定的,除非您將訪問包裝在更高級別的同步原語中(通常建立在原子操作之上)。

簡而言之,如果您沒有額外的工作,編譯器不會提供對位字段的原子同步訪問。

這有幫助嗎?

編輯Dan Grossman 博士有兩節關於原子性和同步性的精彩講座,我在 UOregon 的 CS 部門頁面上找到

寫入位域時,可能有一段時間 window 另一個線程訪問(讀取或寫入)同一結構中的任何(相同或不同)位域的任何嘗試都將導致未定義的行為,這意味着任何事情都可以發生。 讀取位域時,可能有一段時間 window 另一個線程在同一結構中寫入任何位域的任何嘗試都將導致未定義行為。

如果您實際上不能為相關位域使用單獨的變量,您可以在 integer 中存儲多個位域,並通過在位域結構和 32 位 integer 之間創建聯合來自動更新它們,以及然后使用 CompareExchange 序列:

  1. 將位域的值讀取為 Int32。
  2. 將其轉換為位域結構
  3. 更新結構
  4. 將結構轉換回 Int32。
  5. 僅當變量仍保持在 (1) 中讀取的值時,才使用 CompareExchange 用新值覆蓋該變量; 如果值已更改,請從步驟 (1) 重新開始。

為了使這種方法運作良好,步驟 2-4 必須快速。 它們花費的時間越長,步驟 5 中的 CompareExchange 失敗的可能性就越大,因此在 CompareExchange 成功之前必須重新執行步驟 2-4 的次數越多。

如果要以線程安全的方式更新位域,則需要將位域拆分為單獨的標志並使用常規int s 來存儲它們。 訪問單獨的機器字是線程安全的(盡管您需要考慮多處理器系統上的優化和緩存一致性)。

請參閱 Windows聯鎖功能

另請參閱此相關的 SO 問題

只是簡單地使用 atomic.AddInt32 示例:

atomic.AddInt32(&intval, 1 << 0)      //set the first bit
atomic.AddInt32(&intval, 1 << 1) //set the second bit
atomic.AddInt32(&intval, -(1 << 1 + 1 << 0)) //clear the first and second bit

代碼在 Go 中,我認為 c++ 也有類似 atomic.AddInt32 的東西

暫無
暫無

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

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