簡體   English   中英

在C ++隊列中對讀/寫操作進行排序

[英]Ordering of read/write operations in a C++ queue

假設我們有一個SyncQueue類,具有以下實現:

class SyncQueue {
    std::mutex mtx;
    std::queue<std::shared_ptr<ComplexType> > m_q;
public:
    void push(const std::shared_ptr<ComplexType> & ptr) {
        std::lock_guard<std::mutex> lck(mtx);
        m_q.push(ptr);
    }
    std::shared_ptr<ComplexType> pop() {
        std::lock_guard<std::mutex> lck(mtx);
        std::shared_ptr<ComplexType> rv(m_q.front());
        m_q.pop();
        return rv;
    }
};

然后我們有這個使用它的代碼:

SyncQueue q;

// Thread 1, Producer:
std::shared_ptr<ComplexType> ct(new ComplexType);
ct->foo = 3;
q.push(ct);

// Thread 2, Consumer:
std::shared_ptr<ComplexType> ct(q.pop());
std::cout << ct->foo << std::endl;

我打算在打印ct->foo時得到3 mtx為指針本身提供了發生之前的語義,但我不確定是否為ComplexType的內存說了什么。 如果有保證,是否意味着每個互斥鎖( std::lock_guard<std::mutex> lck(mtx); )強制對任何已修改的內存位置進行完全緩存失效,直到獨立內核的內存層次結構為止合並?

std :: mutex()符合Mutex要求( http://en.cppreference.com/w/cpp/concept/Mutex

先前m.unlock()操作在同一個互斥鎖上同步 - 這個鎖定操作(相當於release-acquire std :: memory_order)

release-acquire在這里解釋( http://en.cppreference.com/w/cpp/atomic/memory_order

發布 - 獲取訂購

如果線程A中的原子存儲被標記為memory_order_release並且來自同一變量的線程B中的原子加載被標記為memory_order_acquire, 那么從線程的角度來看, 所有內存都在原子存儲之前寫入(非原子和放松原子) A,在線程B中成為可見的副作用 ,也就是說,一旦原子加載完成,線程B就可以保證看到線程A寫入內存的所有內容。

僅在釋放和獲取相同原子變量的線程之間建立同步。 其他線程可以看到與同步線程中的一個或兩個不同的內存訪問順序。

本節中的代碼示例與您的代碼示例非常相似。 所以應該保證線程1中的所有寫操作都會在push()中的互斥鎖解鎖之前發生。

當然,如果“ct-> foo = 3”沒有任何特殊的棘手意義,其中實際的賦值發生在另一個線程:)

來自cppreference的wrt cache-invalidation:

在強排序系統(x86,SPARC TSO,IBM大型機)上,大多數操作都會自動發布 - 獲取訂購。 沒有為此同步模式發出額外的CPU指令,只會影響某些編譯器優化(例如,禁止編譯器在原子存儲釋放之前移動非原子存儲或者在原子載荷獲取之前執行非原子加載)。 在弱有序系統(ARM,Itanium,PowerPC)上,必須使用特殊的CPU加載或內存柵欄指令。

所以它真的取決於架構。

暫無
暫無

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

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