C++11并发编程:原子操作atomic

原文链接

一:概述

  项目中经常用遇到多线程操作共享数据问题,常用的处理方式是对共享数据进行加锁,如果多线程操作共享变量也同样采用这种方式。

  为什么要对共享变量加锁或使用原子操作?如两个线程操作同一变量过程中,一个线程执行过程中可能被内核临时挂起,这就是线程切换,当内核再次切换到该线程时,之前的数据可能已被修改,不能保证原子操作。

  C++11提供了个原子的类和方法atomic,保证了多线程对变量原子性操作,相比加锁机制mutex.lock(),mutex.unlock(),性能有几倍的提升。

  所需头文件<atomic>

二:错误代码


 
 
  1. //全局变量
  2. int g_num = 0;
  3. void fun()
  4. {
  5. for ( int i = 0; i < 10000000; i++)
  6. {
  7. g_num++;
  8. }
  9. return ;
  10. }
  11. int main()
  12. {
  13. //创建线程1
  14. thread t1(fun);
  15. //创建线程2
  16. thread t2(fun);
  17. t1.join();
  18. t2.join();
  19. cout << g_num << endl;
  20. getchar();
  21. return 1;
  22. }

应该输出结果20000000,实际每次结果都不一样,总是小于该值,正是由于多线程操作同一变量而没有保证原子性导致的。

三:加锁代码


 
 
  1. //全局变量
  2. int g_num = 0;
  3. mutex m_mutex;
  4. void fun()
  5. {
  6. for ( int i = 0; i < 10000000; i++)
  7. {
  8. m_mutex.lock();
  9. g_num++;
  10. m_mutex.unlock();
  11. }
  12. return ;
  13. }
  14. int main()
  15. {
  16. //获取当前毫秒时间戳
  17. typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;
  18. microClock_type tp1 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
  19. long long time1 = tp1.time_since_epoch().count();
  20. //创建线程
  21. thread t1(fun);
  22. thread t2(fun);
  23. t1.join();
  24. t2.join();
  25. cout << "总数:" << g_num << endl;
  26. //获取当前毫秒时间戳
  27. microClock_type tp2 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
  28. long long time2 = tp2.time_since_epoch().count();
  29. cout << "耗时:" << time2 - time1 << "ms" << endl;
  30. getchar();
  31. return 1;
  32. }

执行结果:多次测试输出均为20000000,耗时在3.8s左右

四:atomic原子操作代码


 
 
  1. //全局变量
  2. atomic< int> g_num = 0;
  3. void fun()
  4. {
  5. for ( int i = 0; i < 10000000; i++)
  6. {
  7. g_num++;
  8. }
  9. return ;
  10. }
  11. int main()
  12. {
  13. //获取当前毫秒时间戳
  14. typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;
  15. microClock_type tp1 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
  16. long long time1 = tp1.time_since_epoch().count();
  17. //创建线程
  18. thread t1(fun);
  19. thread t2(fun);
  20. t1.join();
  21. t2.join();
  22. cout << "总数:" << g_num << endl;
  23. //获取当前毫秒时间戳
  24. microClock_type tp2 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
  25. long long time2 = tp2.time_since_epoch().count();
  26. cout << "耗时:" << time2 - time1 << "ms" << endl;
  27. getchar();
  28. return 1;
  29. }

执行结果:多次测试输出均为20000000,耗时在1.3s左右

五:总结

  c++11的原子类atomic相比使用加锁机制性能有2~3倍提升,对于共享变量能用原子类型的就不要再用加锁机制了。

 

  •                     <li class="tool-item tool-active is-like "><a href="javascript:;"><svg class="icon" aria-hidden="true">
                            <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#csdnc-thumbsup"></use>
                        </svg><span class="name">点赞</span>
                        <span class="count">3</span>
                        </a></li>
                        <li class="tool-item tool-active is-collection "><a href="javascript:;" data-report-click="{&quot;mod&quot;:&quot;popu_824&quot;}"><svg class="icon" aria-hidden="true">
                            <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-csdnc-Collection-G"></use>
                        </svg><span class="name">收藏</span></a></li>
                        <li class="tool-item tool-active is-share"><a href="javascript:;"><svg class="icon" aria-hidden="true">
                            <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-csdnc-fenxiang"></use>
                        </svg>分享</a></li>
                        <!--打赏开始-->
                                                <!--打赏结束-->
                                                <li class="tool-item tool-more">
                            <a>
                            <svg t="1575545411852" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5717" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M179.176 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5718"></path><path d="M509.684 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5719"></path><path d="M846.175 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5720"></path></svg>
                            </a>
                            <ul class="more-box">
                                <li class="item"><a class="article-report">文章举报</a></li>
                            </ul>
                        </li>
                                            </ul>
                </div>
                            </div>
            <div class="person-messagebox">
                <div class="left-message"><a href="https://blog.youkuaiyun.com/woniu211111">
                    <img src="https://profile.csdnimg.cn/D/6/9/3_woniu211111" class="avatar_pic" username="woniu211111">
                                            <img src="https://g.csdnimg.cn/static/user-reg-year/2x/10.png" class="user-years">
                                    </a></div>
                <div class="middle-message">
                                        <div class="title"><span class="tit"><a href="https://blog.youkuaiyun.com/woniu211111" data-report-click="{&quot;mod&quot;:&quot;popu_379&quot;}" target="_blank">码农code之路</a></span>
                                                    <span class="flag expert">
                                <a href="https://blog.youkuaiyun.com/home/help.html#classicfication" target="_blank">
                                    <svg class="icon" aria-hidden="true">
                                        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#csdnc-blogexpert"></use>
                                    </svg>
                                    博客专家
                                </a>
                            </span>
                                            </div>
                    <div class="text"><span>发布了134 篇原创文章</span> · <span>获赞 255</span> · <span>访问量 69万+</span></div>
                </div>
                                <div class="right-message">
                                            <a href="https://bbs.youkuaiyun.com/topics/395527914" target="_blank" class="btn btn-sm btn-red-hollow bt-button personal-messageboard">他的留言板
                        </a>
                                                            <a class="btn btn-sm  bt-button personal-watch" data-report-click="{&quot;mod&quot;:&quot;popu_379&quot;}">关注</a>
                                    </div>
                            </div>
                    </div>
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值