C++并发编程之atomic

原子类型对象的主要特点就是从不同线程访问不会导致数据竞争(data race)。因此从不同线程访问某个原子对象是良性 (well-defined) 行为,而通常对于非原子类型而言,并发访问某个对象(如果不做任何同步操作)会导致未定义 (undifined) 行为发生。

std::atomic_flag

  1. std::atomic_flag是一个bool类型的原子变量,它有两个状态set和clear,对应着flag为true和false。

  2. std::atomic_flag使用前必须被ATOMIC_FLAG_INIT初始化,此时的flag为clear状态,相当于静态初始化。

  3. test_and_set():检查当前flag是否被设置。若己设置直接返回true,若没设置则将flag置为true ,并返回false。

  4. clear();清除flag标志,即flag=false。

示例:

#include               // std::cout
#include                 // std::atomic, std::atomic_flag, ATOMIC_FLAG_INIT
#include                 // std::thread, std::this_thread::yield
#include                 // std::vector

std::atomic<bool> ready(false);    // can be checked without being set
std::atomic_flag winner = ATOMIC_FLAG_INIT;    // always set when checked

void count1m(int id)
{
    while (!ready) {        
        std::this_thread::yield();
    } // 等待主线程中设置 ready 为 true.

    for (int i = 0; i < 1000000; ++i) {
    } // 计数.

    // 如果某个线程率先执行完上面的计数过程,则输出自己的 ID.
    // 此后其他线程执行 test_and_set 是 if 语句判断为 false,
    // 因此不会输出自身 ID.
    if (!winner.test_and_set()) {
        std::cout << "thread #" << id << " won!\n";
    }
};

int main()
{
    std::vector<std::thread> threads;
    std::cout << "spawning 10 threads that count to 1 million...\n";
    for (int i = 1; i <= 10; ++i)
        threads.push_back(std::thread(count1m, i));
    ready = true;

    for (auto & th:threads)
        th.join();

    return 0;
}

std::atomic模板类

std::atomic ,UDT类不能有任何虚函数或虚基类,以及必须使用编译器创建的拷贝赋值操作。所有的基类和非静态数据成员也都需要支持拷贝赋值操作。

std::atomic 的构造函数
C++并发编程之atomic_第1张图片
std::atomic::operator=() 函数
C++并发编程之atomic_第2张图片
std::atomic 类模板除了基本类型以外,还针对整形和指针类型做了特化。 特化的 std::atomic 类型支持更多的操作,如 fetch_add, fetch_sub, fetch_and 等。
C++并发编程之atomic_第3张图片

你可能感兴趣的:(C++)