[英]Make access to unsigned char thread-safe (atomic)
我很清楚之前已經提出了類似的問題,而且我也知道,這個操作很可能根本就不是原子的,但是我仍然要求空閑的好奇心,並希望有一些方法可以讓它成為原子。
情況:在struct
內部,有一個名為Busy
的unsigned char變量。 (雖然它可以移出那里並獨立站立)。
此變量Busy
由兩個並發線程修改,一個在調度時設置位,另一個在完成調度操作后清除它們。
現在,調度看起來像這樣:
while(SEC.Busy&(1 << SEC.ReqID))
if(++SEC.ReqID == 5) SEC.ReqID = 0;
sQuery.cData[2] = SEC.ReqID;
而清理bitmaks看起來像這樣:
SEC.Busy &= ~(1 << sQuery->cData[2]);
cData [2]基本上攜帶有關通過網絡使用哪個插槽的信息,並通過另一個線程中的回調返回。
現在的問題是:我怎樣才能確保SEC.Busy(在這種困境中唯一的變量)不會被兩個線程同時試圖改變它而不使用互斥鎖,關鍵部分或任何東西而撕裂如果可能的話?
我也嘗試將SEC.Busy的內容分配給一個局部變量,改變它然后再寫回變量,但不幸的是這個操作似乎也不是原子的。
我目前正在使用Borland C ++ Builder 6,盡管GCC解決方案也可以。
非常感謝你。
C ++ 03(也不是C99)根本沒有說明原子性。 在大多數平台上, 賦值是原子的(=每個人都看到舊值或新值),但由於它沒有同步(=任何人在看到其他更新的新值之后可能看到舊值),無論如何它都是無用的。 任何其他操作,如增量,設置位等都可能不是原子的。
C ++ 11定義了std::atomic
模板 ,它確保原子性和同步,因此您需要使用它。 Boost為大多數C ++ 03編譯器提供了兼容的實現,gcc 從4.2開始就內置了支持 ,它被gcc 4.7中C ++ 11所需的更高級支持所取代
Windows API早就有了“互鎖操作” 。 在引入gcc __sync
函數之前,Unix替代需要匯編(幾個庫提供)。
從多個線程訪問共享數據時有三個潛在的問題。 首先,您可能會在內存訪問過程中獲得一個需要多個總線周期的線程切換; 這被稱為“撕裂”。 其次,每個處理器都有自己的內存緩存,將數據寫入一個緩存不會自動寫入其他緩存,因此不同的線程可以看到過時的數據。 第三,編譯器可以移動指令,以便另一個處理器可以看到稍后存儲到一個變量而不會看到前一個存儲到另一個存儲。
使用unsigned char
類型的變量幾乎肯定會刪除第一個,但它對其他兩個沒有任何影響。
要避免所有這三個問題,請使用C ++ 11中的atomic<unsigned char>
或編譯器和操作系統提供的任何同步技術。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.