• 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 << '
    ';
      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

  • 相关阅读:
    mybatis:mybatis再总结
    shiro:RememberMe
    shiro:session管理
    shiro:缓存管理
    shiro:授权管理
    shiro:密码加密(加密、加盐加密)
    spring:spring再总结(ioc、aop、DI等)
    SpringBoot:整合layui、退出功能
    layui:内置模块(日期与时间、数据表格)
    nuxtjs中配置配置env
  • 原文地址:https://www.cnblogs.com/heimazaifei/p/12176678.html
Copyright © 2020-2023  润新知