CPP(c++) 原子操作



C++中對共享數據的存取在並發條件下可能會引起data race的undifined行為,需要限制並發程序以某種特定的順序執行,
有兩種方式:使用mutex保護共享數據,原子操作:針對原子類型操作要不一步完成,要么不做,不可能出現操作一半被切換CPU,
這樣防止由於多線程指令交叉執行帶來的可能錯誤。非原子操作下,某個線程可能看見的是一個其它線程操作未完成的數據。

std::atomic:例子

class Test
{
public:    
    Test() = default;

    void CThreadFunc()
    {
        for (int i = 0; i < 10000; ++i)
        {
            //std::lock_guard<std::mutex> lck(Test::m_s_ivalue_mutex); //m_iValue需要加鎖才可正常工作
            m_iValue++;

            m_atomic_value++; //不加鎖,也可正常工作
        }
    }

    void Start()
    {
        std::vector<std::thread> threads;
        for (int i = 0; i < 10; ++i)
        {
            threads.push_back(std::thread(&Test::CThreadFunc, this));
        }

        for (auto& th : threads)
        {
            if (th.joinable())
            {
                th.join();
            }
        }
     std::cout << "m_iValue:" << m_iValue << ", m_atomic_value:" << m_atomic_value << std::endl;
    }

private:
    int m_iValue = 0;
    std::atomic<int> m_atomic_value = 0; //sta::atomic<T> 原子操作,可以替換為atomic_int m_atomic_value(0); 該方法對bool、long,char等適用 
    static std::mutex m_s_ivalue_mutex;
};

atomic_flag:例子

  //atomic_flag只支持兩種操作,test-and-set 和 clear。
  //test_and_set() 函數檢查 std::atomic_flag 標志,如果 std::atomic_flag 之前沒有被設置過,
     //則設置 std::atomic_flag 的標志,並返回先前該 std::atomic_flag 對象是否被設置過,
     //如果之前 std::atomic_flag 對象已被設置,則返回 true,否則返回 false。
  //clear  清除標志

// using atomic_flag as a lock
#include <iostream>       // std::cout
#include <atomic>         // std::atomic_flag
#include <thread>         // std::thread
#include <vector>         // std::vector
#include <sstream>        // std::stringstream

std::atomic_flag lock_stream = ATOMIC_FLAG_INIT; // 設置並,初始化為false
std::stringstream stream;

void append_number(int x) {
  while (lock_stream.test_and_set()) {}
  stream << "thread #" << x << '\n';
  lock_stream.clear();
}

int main ()
{
  std::vector<std::thread> threads;
  for (int i=1; i<=10; ++i) threads.push_back(std::thread(append_number,i));
  for (auto& th : threads) th.join();
  std::cout << stream.str();
  return 0;
}

Possible output (order of lines may vary):
thread #1
thread #2
thread #3
thread #4
thread #5
thread #6
thread #7
thread #8
thread #9
thread #10


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM