簡體   English   中英

線程本地獲取/釋放同步

[英]Thread-local acquire/release synchronization

通常,load-acquire / store-release同步是C ++ 11內存模型中最常見的基於內存排序的同步形式之一。 它基本上是互斥體提供內存排序的方式。 負載獲取和存儲釋放之間的“關鍵部分”總是在不同的觀察者線程之間同步,因為所有觀察者線程都會同意獲取之后和發布之前發生的事情。

通常,這是通過讀取 - 修改 - 寫入指令(如比較交換)以及進入臨界區時的獲取屏障以及退出臨界區時具有釋放屏障的另一個讀取 - 修改 - 寫入指令來實現的。

但是在某些情況下,您可能在load-acquire和release-store之間有一個類似的關鍵部分 [1],除了只有一個線程實際修改了同步變量。 其他線程可能會讀取同步變量,但只有一個線程實際修改它。 在這種情況下,進入臨界區時,不需要讀 - 修改 - 寫指令。 您只需要一個簡單的商店,因為您沒有與試圖修改同步標志的其他線程競爭。 (這可能看起來很奇怪,但請注意許多無鎖內存回收延遲模式,如用戶空間RCU或基於紀元的回收,使用線程本地同步變量,只能由一個線程寫入,但由許多線程讀取,所以這不是一種奇怪的情況。)

因此,當進入關鍵部分時,您可以執行以下操作:

sync_var.store(true, ...);

.... critical section ....

sync_var.store(false, std::memory_order_release);

沒有競爭,因為當只有一個線程需要設置/取消設置臨界區變量時,不需要進行讀 - 修改 - 寫。 其他線程可以通過load-acquire簡單地讀取臨界區變量。

問題是,當您進入臨界區時,您需要獲取操作或圍欄。 但是你不需要做一個LOAD,只需要一個STORE。 那么,當您真正需要商店時,制作獲取訂購的好方法是什么? 我看到只有兩個真正的選項屬於C ++內存模型。 或者:

  1. 使用exchange而不是商店,因此您可以執行sync_var.exchange(true, std::memory_order_acquire) 這里的缺點是,當你真正需要的只是一個簡單的商店時,交換是一個更重量級的讀 - 修改 - 寫操作。
  2. 插入“虛擬”加載獲取,如:

    (無效)sync_var.load(標准:: memory_order_acquire); sync_var.store(true,std :: memory_order_relaxed);

“虛擬”負載獲取似乎更好。 據推測,編譯器無法優化掉未使用的負載,因為它是一個原子指令,具有與sync_var上的釋放操作產生“同步 - ”關系的sync_var 但它似乎也非常hacky,如果沒有評論解釋正在發生的事情,目的還不清楚。

那么,當我們需要做的只是一個簡單的商店時,產生獲取語義的最佳方法是什么?


[1]我松散地使用術語“臨界區”。 我不一定是指通過互斥方式訪問的部分。 相反,我只是指通過acquire-release語義同步內存排序的任何部分。 這可能是指互斥鎖,或者它可能只是指RCU之類的東西,其中臨界區可以由多個讀者同時訪問。

您的邏輯中的缺陷是不需要原子RMW,因為關鍵部分中的數據由單個線程修改,而所有其他線程僅具有讀訪問權限。
這不是真的; 在閱讀和寫作之間仍然需要有明確的順序。 您不希望在另一個線程仍在讀取數據時修改數據。 因此,每個線程在完成訪問數據時都需要通知其他線程。

通過僅使用原子庫來進入臨界區,無法建立“同步 - 關系”關系。 獲取/釋放同步基於運行時關系,其中收集器僅在觀察到原子負載返回的特定值之后才知道同步完成。 這是永遠無法通過單個原子存儲實現的,因為一個修改線程可以隨時更改原子變量sync_var ,因此無法知道另一個線程是否仍在讀取數據。

具有“虛擬” load/acquire的選項也是無效的,因為它無法通知其他線程它想要獨占訪問。 您嘗試通過使用單個(寬松)存儲來解決此問題,但是加載和存儲是可以被其他線程中斷的單獨操作(即,多個線程同時訪問關鍵區域)。

每個線程必須使用原子RMW來加載特定值,同時更新變量以通知它現在具有獨占訪問權的所有其他線程(無論是讀取還是寫入)。

void lock()
{
    while (sync_var.exchange(true, std::memory_order_acquire));
}

void unlock()
{
    sync_var.store(false, std::memory_order_release);
}

在多個線程同時具有讀訪問權限的情況下(例如, std::shared_mutex ),可以進行優化。

暫無
暫無

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

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