面向的问题
对简单临界资源的访问,如果使用mutex开销较大。
如有两个线程,对一个变量进行操作,一个线程读这个变量的值,一个线程往这个变量中写值。即使是一个简单变量的读取和写入操作,如果不加锁,也有可能会导致读写值混乱(一条语句可能会被拆成3、4条汇编语句来执行,所以仍然有可能混乱)
1 #include <iostream>
2 #include <thread>
3 using namespace std;
4 int g_count = 0;
5
6 void mythread1() {
7 for (int i = 0; i < 1000000; i++) {
8 g_count++;
9 }
10 }
11
12 int main() {
13 std::thread t1(mythread1);
14 std::thread t2(mythread1);
15 t1.join();
16 t2.join();
17 cout << "正常情况下结果应该是200 0000次,实际是" << g_count << endl;
18 }
使用std::mutex来解决上述对临界资源访问的问题。结果正常,但是每一次循环都要加锁解锁是的程序开销很大。
1 #include <iostream>
2 #include <thread>
3 #include <mutex>
4 using namespace std;
5 int g_count = 0;
6 std::mutex mymutex;
7
8 void mythread1() {
9 for (int i = 0; i < 1000000; i++) {
10 std::unique_lock<std::mutex> u1(mymutex);
11 g_count++;
12 }
13 }
14
15
16 int main() {
17 std::thread t1(mythread1);
18 std::thread t2(mythread1);
19 t1.join();
20 t2.join();
21 cout << "正常情况下结果应该是200 0000次,实际是" << g_count << endl;
22 }
std::atomic
std::atomic
1 #include <iostream>
2 #include <thread>
3 #include <atomic>
4 using namespace std;
5 std::atomic<int> g_count = 0; //封装了一个类型为int的 对象(值)
6
7 void mythread1() {
8 for (int i = 0; i < 1000000; i++) {
9 g_count++;
10 }
11 }
12
13 int main() {
14 std::thread t1(mythread1);
15 std::thread t2(mythread1);
16 t1.join();
17 t2.join();
18 cout << "正常情况下结果应该是200 0000次,实际是" << g_count << endl;
19 }
一般atomic原子操作,针对++,–,+=,-=,&=,|=,^=是支持的,其他操作不一定支持。如下使用g_count= g_count+1就会产生错误。
1 #include <iostream>
2 #include <thread>
3 #include <atomic>
4 using namespace std;
5 std::atomic<int> g_count = 0; //封装了一个类型为int的 对象(值)
6
7 void mythread1() {
8 for (int i = 0; i < 1000000; i++) {
9 //虽然g_count使用了原子操作模板,但是这种写法既读又写,
10 //会导致计数错误
11 g_count = g_count + 1;
12 }
13 }
14
15 int main() {
16 std::thread t1(mythread1);
17 std::thread t2(mythread1);
18 t1.join();
19 t2.join();
20 cout << "正常情况下结果应该是200 0000次,实际是" << g_count << endl;
21 }
其他需要注意的地方
1 std::atomic<int> atm = 0;
2
3 cout << atm << endl;
这里只有读取atm是原子操作,但是整个这一行代码 cout << atm << endl; 并不是原子操作,导致最终显示在屏幕上的值是一个“曾经值”。
1 std::atomic<int> atm = 0;
2
3 auto atm2 = atm; //不可以
这种拷贝初始化不可以,会报错。
atomic<int> atm2(atm.load());
load():以原子方式读atomic对象的值。
atm2.store(12);
store():以原子方式写。
参考
https://blog.csdn.net/qq_38231713/article/details/106093115
原文链接: https://www.cnblogs.com/chen-cs/p/13254219.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/199997
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!