数据的共享
- 只读数据是安全稳定的,不需要进行保护。直接读就行。
- 读写数据,互斥访问。读写锁。读写不能同时进行、只能一个写、可以多个一起读。
多线程被分配在多个cpu上运行,提高效率。但多个线程访问内存中的同一数据资源时,如果不加以保护就会发生读写的错误。访问公共数据的代码成为临界区。具体参见<操作系统>。为了保证数据的一致性,使用互斥量进行加锁。使用头文件#include<mutex>
。
mutex
互斥量是一个类对象,多个线程尝试使用成员函数lock()
进行加锁,保护临界区。
lock()
和unlock()
成对使用。
//创建读写类,类的多个成员函数供线程进行调用。
class readAndWrite
{
public:
void writeMsg() {
for (int i = 0; i < 100; i++) {
cout << "writeMsg()执行,插入一个元素 num = " << i << endl;
m_mutex.lock();//两个函数都要访问msgRecvQue,需要进行保护。写的时候不能读,不然会发生错误。
msgRecvQue.push_back(i);
m_mutex.unlock();//加锁必须解锁,保护临界区,成对出现。
}
}
void readMsg() {
int res = 0;
for (int i = 0; i < 100; i++) {
if (!msgRecvQue.empty()) {
m_mutex.lock();
res = msgRecvQue.front();
msgRecvQue.pop_front();
cout << "readMsg()执行,读取到一个元素 num = " << res << endl;
m_mutex.unlock();
}
else {
cout << "msgRecv is empty!" << endl;
}
}
}
private:
list<int> msgRecvQue;//消息队列
mutex m_mutex;
};
int main() {
readAndWrite obj;
thread readThread(&readAndWrite::readMsg, &obj);
thread writeThread(&readAndWrite::writeMsg, &obj);
readThread.join();
writeThread.join();
return 0;
}
使用
lock_guard
类模板自动加锁和解锁。取代lock()
和unlock()
。其实是在构造函数里面调用lock()
,析构函数里面调用unlock()
。
{
lock_guard<mutex> sbguard(m_mutex);
--------- 临界区---------------
}
进入临界区调用构造函数加锁,出临界区调用析构函数解锁。