在线程间共享数据:
所有的线程间共享数据的问题,都是修改数据导致的。
如果所有的共享数据是只读的,就没有问题,因为一个线程所读取的数据不受另一个线程是否正在读取相同的数据而影响
但是,如果数据在线程间共享,同时一个或者多个线程开始修改数据,就会有很多麻烦。
用互斥元保护共享数据:
在访问共享数据结构之前,锁定(lock)与该数据相关的互斥元,当访问数据结构完成后,解锁(unlock)该互斥元。
线程库会确保一旦一个线程已经锁定某个互斥元,所有其他试图锁定相同互斥元的线程必须等待。直到此互斥元被解锁
通过构造std::mutex 的实例来创建互斥元,调用成员函数lock()来锁定它,调用成员函数unlock()来解锁它
c++库提供了std::lock_guard类模版,在构造时锁定所给的互斥元,在析构时将互斥元解锁,从而保证被锁定的互斥元始终被正确解锁
例子:
#include <iostream>
#include <mutex>
#include <algorithm>
#include <list>
#include <thread>
using namespace std;
list<int>some_list;
mutex some_mutex;
template<class T>
class Lock_guard
{
private:
T* Mutex;
public:
Lock_guard(T& x)
{
Mutex = &x;
Mutex->lock();
}
~Lock_guard()
{
Mutex->unlock();
}
};
class Thread_guard
{
private:
thread& t;
public:
explicit Thread_guard(thread& t_):t(t_){}
~Thread_guard()
{
if(t.joinable())
t.join();
}
Thread_guard(Thread_guard const&)=delete;
Thread_guard& operator=(Thread_guard const&)=delete;
};
void add_to_list(int new_value)
{
Lock_guard<mutex>guard(some_mutex);
some_list.push_back(new_value);
}
bool list_contains(int value_to_find)
{
Lock_guard<mutex>guard(some_mutex);
return (find(some_list.begin(), some_list.end(), value_to_find)!=some_list.end());
}
int main()
{
thread x(add_to_list,1);
Thread_guard xg(x);
thread x2(add_to_list,2);
Thread_guard xg2(x2);
thread x3(add_to_list,3);
Thread_guard xg3(x3);
thread x4(add_to_list,4);
Thread_guard xg4(x4);
list<int>::iterator it = some_list.begin();
while (it!=some_list.end()) {
cout<<*it<<endl;
it++;
}
return 0;
}