1、原子操作介绍
在多线程编程中,经常使用互斥锁锁住一段代码块,实现线程同步。原子操作可以看成是对变量的互斥锁。比如程序中一个线程读取一个变量,另一个线程修改该变量的值,那么采用原子操作可以不用添加互斥锁即可实现线程同步。
2、原子操作实例
采用原子操作,定义了一个全局变量iCount。
#include <thread>
#include <atomic>
#include <iostream>
#include <vector>
std::atomic<int> iCount(0);
void threadFunc1()
{
for (size_t i = 0; i < 100; i++)
{
std::cout << "iCount = " << iCount++ << std::endl;
}
return;
}
void threadFunc2()
{
for (size_t i = 0; i < 100; i++)
{
std::cout << "iCount = " << iCount-- << std::endl;
}
return;
}
int main(int argc, char **argv)
{
std::vector<std::thread> vecThread;
for (size_t i = 0; i < 100; i++)
{
vecThread.push_back(std::thread(threadFunc1));
}
for (size_t i = 0; i < 100; i++)
{
vecThread.push_back(std::thread(threadFunc2));
}
for (auto &th : vecThread)
{
th.join();
}
std::cout << "Finally iCount = " << iCount.load() << std::endl;
return 0;
}
输出结果是0.
如果不采用原子操作:
#include <thread>
#include <atomic>
#include <iostream>
#include <vector>
int iCount = 0;
void threadFunc1()
{
for (size_t i = 0; i < 100; i++)
{
std::cout << "iCount = " << iCount++ << std::endl;
}
return;
}
void threadFunc2()
{
for (size_t i = 0; i < 100; i++)
{
std::cout << "iCount = " << iCount-- << std::endl;
}
return;
}
int main(int argc, char **argv)
{
std::vector<std::thread> vecThread;
for (size_t i = 0; i < 100; i++)
{
vecThread.push_back(std::thread(threadFunc1));
}
for (size_t i = 0; i < 100; i++)
{
vecThread.push_back(std::thread(threadFunc2));
}
for (auto &th : vecThread)
{
th.join();
}
std::cout << "Finally iCount = " << iCount << std::endl;
return 0;
}
输出结果是-5, 而且每次运行,结果都不一样。
3、注意事项
原子操作的初始化不能写成如下形式
std::atomic<int> iCount = 0;
会出现编译错误 error: use of deleted function
如果使用cmake编译,需要添加Threads库,本文采用的CMakeLists.txt文件如下
cmake_minimum_required(VERSION 2.8.0)
project(atomic_test)
find_package(Threads REQUIRED)
add_executable(test_with_atomic test_with_atomic.cpp)
target_link_libraries(test_with_atomic Threads::Threads)
add_executable(test_without_atomic test_without_atomic.cpp)
target_link_libraries(test_without_atomic Threads::Threads)