1. 程式人生 > >C++原子操作

C++原子操作

為什麼要使用原子操作

  1. 讀和寫不是atomic
  2. 編譯器生成的程式碼有可能改變操作次序
    使用mutex兩個問題都可以解決,但代價比較昂貴,所以用atomic取代。

用例

#include <atomic>    // for atomics
#include <future>    // for async() and futures
#include <thread>    // for this_thread
#include <chrono>    // for durations
#include <iostream>
long data; std::atomic<bool> readyFlag(false); void provider () { // after reading a character std::cout << "<return>" << std::endl; std::cin.get(); // provide some data data = 42; // and signal readiness readyFlag.store(true); } void consumer () {
// wait for readiness and do something else while (!readyFlag.load()) { std::cout.put('.').flush(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); } // and process provided data std::cout << "\nvalue : " << data << std::endl; } int main
() { // start provider and consumer auto p = std::async(std::launch::async,provider); auto c = std::async(std::launch::async,consumer); std::atomic<int> x{0}; int x0 = x; std::cout << "x = " << x << std::endl; while ( !x.compare_exchange_strong(x0, x0+1) ) {} std::cout << "x = " << x << std::endl; }

編譯後執行:

$ ./atomics 
<return>
x = 0
x = 1
....

value : 42

常用介面

假設有一個原子變數a

  • a.store(val):賦值val返回void
  • a.load():返回a的拷貝
  • a.exchange(val):賦值val並返回舊值a的拷貝
  • a.compare_exchange_strong(exp, des)
  • a.compare_exchange_weak(exp, des)
    上面兩個操作是CAS(compare-and-swap)操作,比較“某記憶體區內容“和”某給定值“,並且唯有在它們相同時才將記憶體區內容更新為另一個給定的新值。
    例如:
bool success = x.compare_exchange_strong(y, z);
// If x==y, make x=z and return true
// Otherwise, set y=x and return false

這兩個操作常用做無鎖演算法