簡體   English   中英

獲取c ++ 11(原子)的發布操作

[英]Acquire release operation of c++11(atomic)

#include <atomic>
#include <iostream>
#include <thread>

class atomicAcquireRelease00
{
public:
    atomicAcquireRelease00() : x(false), y(false), z(0) {}
    void run()
    {
        std::thread a(&atomicAcquireRelease00::write_x, this);
        std::thread b(&atomicAcquireRelease00::write_y, this);
        std::thread c(&atomicAcquireRelease00::read_x_then_y, this);
        std::thread d(&atomicAcquireRelease00::read_y_then_x, this);

        a.join();
        b.join();
        c.join();
        d.join();

        std::cout<<"z == "<<z.load()<<std::endl;
    }

private:
    void write_x()
    {                
        x.store(true, std::memory_order_release); //(1)
    }

    void write_y()
    {           
        y.store(true, std::memory_order_release); //(2)
    }

    void read_x_then_y()
    {            
        while(!x.load(std::memory_order_acquire)); //(3)
        if(y.load(std::memory_order_acquire)){    //(4)
            ++z;
        }
    }

    void read_y_then_x()
    {           
        while(!y.load(std::memory_order_acquire));  //(5)
        if(x.load(std::memory_order_acquire)){      //(6)
            ++z;
        }

    }

private:
    std::atomic<bool> x, y;
    std::atomic<int> z;
};            

int main()
{
   for(size_t i = 0; i != 50; ++i){
     atomicAcquireRelease00().run();
   }          

  return 0;
}

atomicAcquireRelease00在加載值時不遵守順序。 據我所知,如果我將操作存儲聲明為std::memory_order_release並將操作加載為std::memory_order_acquire作為一對,則加載和存儲在同一原子變量上的操作將同步,但這個簡單示例不會按照我的預期工作。

這個過程基於我的想象力

  • 案例A:

    1. x設為true
    2. at(4),y.load返回false,z保持為零
    3. y設為真
    4. 在(6)之后,z成為一個
  • 案例B:

    1. y設為真
    2. at(6),x.load返回false,z保持為零
    3. x設為true
    4. 在(4)之后,z成為一個
  • 案例C:

    1. x設為true,y設為true
    2. 在(4)和(6)之后,z變為2

我不能保證xy將被設置為true第一,但是當x設置為true,負荷x應該與它以及同步y,那么什么樣的情況會令z保持為零?

正是 Anthony Williams的“Concurrency In Action”中的示例清單5.7。

他解釋說:

在這種情況下,斷言可以觸發(就像在寬松排序的情況下一樣),因為x的加載和y的加載都可能讀取為false x和y由不同的線程寫入 ,因此在每種情況下從發布到獲取的排序對其他線程中的操作沒有影響。

在此輸入圖像描述

除非使用seq_cst,否則C / C ++ 11不保證存儲到不同內存位置的總順序。 因此,每個線程都可以以不同的順序自由查看商店。 獲取 - 釋放同步沒有幫助,因為它只是從執行存儲的線程到執行加載的線程。 如果你想玩這樣的單元測試並更好地發展你的直覺,試試CDSChecker。 它是一個工具,可以向您顯示C11的任何實際實現可能產生的所有行為。

暫無
暫無

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

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