zoukankan      html  css  js  c++  java
  • C++11并发编程:原子操作atomic

    一:概述

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

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

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

      所需头文件<atomic>

    二:错误代码

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

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

    三:加锁代码

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

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

    四:atomic原子操作代码

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

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

    五:总结

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

    作者:蜗牛201
    出处:https://www.cnblogs.com/woniu201/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
    如果文中有什么错误,欢迎指出。以免更多的人被误导。
  • 相关阅读:
    jdbc操作元数据
    jdbc完成增删改查
    jdbc原理
    JDBC快速入门
    DOM_调查问卷效果2
    DOM_radio
    DOM_mail效果
    css基础
    《POSIX多线程程序设计》读书笔记
    《(转载)Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)》
  • 原文地址:https://www.cnblogs.com/buzhidao1/p/13409940.html
Copyright © 2011-2022 走看看