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倍提升,对于共享变量能用原子类型的就不要再用加锁机制了。

扫码关注公众号

专注分享Java,C/C++,STL,Spring框架,mybatis框架,mysql,redis,分布式,高并发,设计模式,爬虫,docker,shell编程等相关技术,在这里一起探讨,一起学习,一起进步,不定期分享视频书籍资源,充分利用碎片化时间,让我们的技术之路更加有乐趣。

posted @ 2018-12-14 15:16  蜗牛201  阅读(733)  评论(0编辑  收藏  举报