一、原子操作
1.1原子操作概念例子
互斥量:多线程编程中保护共享数据:锁,操作共享数据,开锁
有两个线程,对一个变量进行操作,这个线程读,另一个线程往变量中写值。
int atomvalue = 5;
读线程A:
int tmpvalue = atomvalue;//atomvalue代表的是多个线程之间要共享的变量
写线程B:
atomvalue = 6;
结果:读出一个不可预料的中间值
原子操作:
可以把原子操作理解为一种:不需要用到互斥量加锁(无锁)技术的多线程编程方式
多线程中不会被打断的程序执行片段
互斥量:加锁一般针对一个代码段(几行代码)
原子操作:针对的一般都是一个变量,而不是一个代码段
一般指“不可分割的操作”
std::atomic来代表原子操作,std::atomic是个类模板。其实std::atomic这个东西是用来封装某个类型的值的
#include <thread>
#include <atomic>
std::atomic<int> g_mycount;
void mythread()
{
for (int i = 0;i < 10000000;i++)
{
g_mycount++;
}
return;
}
int main()
{
std::thread myobj1(mythread);
std::thread myobj2(mythread);
myobj1.join();
myobj2.join();
cout << "两个线程执行完毕,最终的g_mycount的结果是: " << g_mycount << endl;
}
结果:
两个线程执行完毕,最终的g_mycount的结果是: 20000000
注意:
不能写成std::atomic<int> g_mycount = 0;
,否则
error: use of deleted function ‘std::atomic<int>::atomic(const std::atomic<int>&)’
std::atomic<int> g_mycount = 0;
std::atomic<bool> g_ifend;
void mythread()
{
std::chrono::milliseconds dura(1000);
while (g_ifend == false)
{
cout << "thread id = " << std::this_thread::get_id() << "运行中..." << endl;
std::this_thread::sleep_for(dura);
}
cout << "thread id = " << std::this_thread::get_id() << "运行结束..." << endl;
return;
}
int main()
{
std::thread myobj1(mythread);
std::thread myobj2(mythread);
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
g_ifend = true;
myobj1.join();
myobj2.join();
cout << "程序执行完毕,退出" << endl;
return 0;
}
结果
thread id = thread id = 140104806115072140104797722368运行中...运行中...
thread id = 140104806115072运行中...
thread id = 140104797722368运行中...
thread id = 140104806115072运行中...
thread id = 140104797722368运行中...
thread id = 140104806115072运行中...
thread id = 140104797722368运行中...
thread id = 140104806115072运行中...
thread id = 140104797722368运行中...
thread id = 140104806115072运行结束...
thread id = 140104797722368运行结束...
程序执行完毕,退出
1.2 一点心得
一般用于计数或者统计(累计发出了多少个数据包,累计接受到了多少数据包)
二、原子操作续谈
2.1 合法操作符
一般atomic原子操作,针对++,–,+=,&=,|=,^=
cout << atm << endl;
读atm是个原子操作,但整个一行代码并不是原子操作;屏幕看到的atm并不是atm的最新值
2.2 赋值
atuo atm2 = atm;
原子变量这种定义不允许,显示“尝试引用已删除的函数”
load()以原子方式读atomic对象的值:
atomic<int> atm2(atm.load());
store()以原子方式写入内容:
atm2.store();