C++ lock_guard
2019-04-04 本文已影响0人
louyang
可能被多个线程修改的数据,我们一般用互斥量(mutex)来保护。
mutex在同一时间,只能被一个线程拿到(专业术语叫lock), 其他试图lock mutex的线程会被挂起,直到该mutex被释放后,才有可能拿到mutex并继续执行。
先看一个没有mutex的例子:
#include <thread>
#include <iostream>
int global = 0;
void threadTask()
{
for (int i = 0; i < 100000000; i++) {
global++;
}
std::cout << global << std::endl;
}
int main()
{
std::thread t1(threadTask);
std::thread t2(threadTask);
std::thread t3(threadTask);
t1.join();
t2.join();
t3.join();
}
运行结果:
$ g++ a.cpp -lpthread
$ ./a.out
300000000
$ ./a.out
297532046
这个程序有3个线程,每个线程各做1亿次自加。因为没有mutex保护,运行结果并不总是3亿。
再看一个例子:
#include <iostream>
#include <chrono>
#include <thread>
#include <list>
#include <algorithm>
#include <mutex>
std::list<int>myList;
std::mutex myMutex;
using namespace std::chrono_literals;
void addToList(int data)
{
std::lock_guard<std::mutex> guard(myMutex);
myList.push_back(data);
}
void addThread(int max, int interval)
{
for (int i = 0; i < max; i++) {
if( (i % interval) == 0) {
addToList(i);
}
std::this_thread::sleep_for(1s);
}
}
void printList()
{
std::lock_guard<std::mutex> guard(myMutex);
for (auto i : myList) {
std::cout << i << ",";
}
std::cout << "----" << std::endl;
}
void printThread()
{
for (int i = 0; i < 100; i++) {
printList();
std::this_thread::sleep_for(1s);
}
}
int main()
{
int max = 100;
std::thread t1(addThread, max, 1);
std::thread t2(addThread, max, 10);
std::thread t3(printThread);
t1.join();
t2.join();
t3.join();
return 0;
}
$ g++ a.cpp -lpthread && ./a.out
----
0,0,----
0,0,1,----
0,0,1,2,----
0,0,1,2,3,----
0,0,1,2,3,4,----
0,0,1,2,3,4,5,----
0,0,1,2,3,4,5,6,----
0,0,1,2,3,4,5,6,7,----
0,0,1,2,3,4,5,6,7,8,----
0,0,1,2,3,4,5,6,7,8,9,10,----
0,0,1,2,3,4,5,6,7,8,9,10,10,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,14,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,14,15,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,14,15,16,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,14,15,16,17,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,14,15,16,17,18,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,14,15,16,17,18,19,20,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,14,15,16,17,18,19,20,20,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,14,15,16,17,18,19,20,20,21,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,14,15,16,17,18,19,20,20,21,22,----
0,0,1,2,3,4,5,6,7,8,9,10,10,11,12,13,14,15,16,17,18,19,20,20,21,22,23,----