保护共享数据,用代码把共享数据锁住,其他想操作共享数据的线程得等待解锁。
互斥量的概念:
互斥量是个类对象。多个线程尝试lock锁上。结果:只有一个线程能够锁定成功,成功的标志是lock函数返回。如果没锁成功,那么流程就会卡在lock这,不断尝试去锁,一直到成功。
互斥量使用起来要小心,保护数据不要多也不要少,少了程序该崩溃还是崩溃,多了影响程序的运行效率。
互斥量的用法:
头文件
#include//互斥量
步骤:先lock(),操作共享数据,unlock();
lock()和unlock()要成对使用。
static int num_push = 0;
static int num_pop = 0;
class A {
std::listmsgReceive;
std::mutex my_mutex;//创建一个互斥量的成员变量
public:
void inMsgRecQueue()
{
for (int i = 0; i < 100; ++i)
{
cout << ++num_push << endl;
my_mutex.lock();
msgReceive.push_back(i);
my_mutex.unlock();
}
}
bool booloutMsg(int &commend)
{
my_mutex.lock();
if (!msgReceive.empty())
{
cout << ++num_pop << endl;
//消息不为空
int commend = msgReceive.front();
msgReceive.pop_front();
my_mutex.unlock();
//...其他处理
return true;
}
cout << ++num_pop << endl;
my_mutex.unlock();
return false;
}
void outMsgRecQuene()
{
int commend = 0;
for (int i = 0; i < 100; ++i)
{
bool result = booloutMsg(commend);
if (result==true)
{
//成功处理
}
else
{
//消息为空
cout << "outMsgRecQuene执行,但是消息队列为空!" << endl;
}
}
}
};
int main()
{
A a;
std::thread myOutMsg(&A::outMsgRecQuene, &a);
std::thread myRecMsg(&A::inMsgRecQueue, &a);
myOutMsg.join();
myRecMsg.join();
cout << "num_push = " << num_push << endl
<< "num_pop = " << num_pop << endl;
return 0;
}
std::lock_guard text
构造函数里执行了mutex的lock(),析构函数里执行了mutex的unlock()。
但是不太灵活,必须要等析构函数执行才会解锁。
lock_guard实例
static int num_push = 0;
static int num_pop = 0;
class A {
std::listmsgReceive;
std::mutex my_mutex;//创建一个互斥量的成员变量
public:
void inMsgRecQueue()
{
for (int i = 0; i < 100; ++i)
{
cout << ++num_push << endl;
std::lock_guard test_lock(my_mutex);
msgReceive.push_back(i);
}
}
bool booloutMsg(int &commend)
{
std::lock_guard test_lock(my_mutex);
if (!msgReceive.empty())
{
cout << ++num_pop << endl;
//消息不为空
int commend = msgReceive.front();
msgReceive.pop_front();
//...其他处理
return true;
}
cout << ++num_pop << endl;
return false;
}
void outMsgRecQuene()
{
int commend = 0;
for (int i = 0; i < 100; ++i)
{
bool result = booloutMsg(commend);
if (result==true)
{
//成功处理
}
else
{
//消息为空
cout << "outMsgRecQuene执行,但是消息队列为空!" << endl;
}
}
}
};
int main()
{
A a;
std::thread myOutMsg(&A::outMsgRecQuene, &a);
std::thread myRecMsg(&A::inMsgRecQueue, &a);
myOutMsg.join();
myRecMsg.join();
cout << "num_push = " << num_push << endl
<< "num_pop = " << num_pop << endl;
return 0;
}
死锁
产生的前提条件:是由至少两个互斥量才会产生这个问题。
static int num_push = 0;
static int num_pop = 0;
class A {
std::listmsgReceive;
std::mutex my_mutex1,my_mutex2;//创建一个互斥量的成员变量
public:
void inMsgRecQueue()
{
for (int i = 0; i < 100; ++i)
{
cout << ++num_push << endl;
my_mutex1.lock();
my_mutex2.lock();
msgReceive.push_back(i);
my_mutex2.unlock();
my_mutex1.unlock();
}
}
bool booloutMsg(int &commend)
{
my_mutex2.lock();
my_mutex1.lock();
if (!msgReceive.empty())
{
cout << ++num_pop << endl;
//消息不为空
int commend = msgReceive.front();
msgReceive.pop_front();
//...其他处理
my_mutex2.unlock();
my_mutex1.unlock();
return true;
}
my_mutex2.unlock();
my_mutex1.unlock();
cout << ++num_pop << endl;
return false;
}
void outMsgRecQuene()
{
int commend = 0;
for (int i = 0; i < 100; ++i)
{
bool result = booloutMsg(commend);
if (result==true)
{
//成功处理
}
else
{
//消息为空
cout << "outMsgRecQuene执行,但是消息队列为空!" << endl;
}
}
}
};
int main()
{
A a;
std::thread myOutMsg(&A::outMsgRecQuene, &a);
std::thread myRecMsg(&A::inMsgRecQueue, &a);
myOutMsg.join();
myRecMsg.join();
cout << "num_push = " << num_push << endl
<< "num_pop = " << num_pop << endl;
return 0;
}
一般解决方案:只要顺序不搞乱,就不会出现死锁。
std::lock()函数模板:两个互斥量的时候才使用
要么两个互斥量都锁住,要么两个互斥量都没锁住。
static int num_push = 0;
static int num_pop = 0;
class A {
std::listmsgReceive;
std::mutex my_mutex1,my_mutex2;//创建一个互斥量的成员变量
public:
void inMsgRecQueue()
{
for (int i = 0; i < 100; ++i)
{
cout << ++num_push << endl;
std::lock(my_mutex1, my_mutex2);
msgReceive.push_back(i);
my_mutex2.unlock();
my_mutex1.unlock();
}
}
bool booloutMsg(int &commend)
{
std::lock(my_mutex1, my_mutex2);
if (!msgReceive.empty())
{
cout << ++num_pop << endl;
//消息不为空
int commend = msgReceive.front();
msgReceive.pop_front();
//...其他处理
my_mutex2.unlock();
my_mutex1.unlock();
return true;
}
my_mutex2.unlock();
my_mutex1.unlock();
cout << ++num_pop << endl;
return false;
}
void outMsgRecQuene()
{
int commend = 0;
for (int i = 0; i < 100; ++i)
{
bool result = booloutMsg(commend);
if (result==true)
{
//成功处理
}
else
{
//消息为空
cout << "outMsgRecQuene执行,但是消息队列为空!" << endl;
}
}
}
};
int main()
{
A a;
std::thread myOutMsg(&A::outMsgRecQuene, &a);
std::thread myRecMsg(&A::inMsgRecQueue, &a);
myOutMsg.join();
myRecMsg.join();
cout << "num_push = " << num_push << endl
<< "num_pop = " << num_pop << endl;
return 0;
}
std::lock_guard<mutex> test(my_mutex1, std::adopt_lock);
表示之前已经锁过了。
static int num_push = 0;
static int num_pop = 0;
class A {
std::listmsgReceive;
std::mutex my_mutex1,my_mutex2;//创建一个互斥量的成员变量
public:
void inMsgRecQueue()
{
for (int i = 0; i < 100; ++i)
{
cout << ++num_push << endl;
std::lock(my_mutex1, my_mutex2);
std::lock_guard test(my_mutex1, std::adopt_lock);
std::lock_guard test1(my_mutex2, std::adopt_lock);
msgReceive.push_back(i);
}
}
bool booloutMsg(int &commend)
{
std::lock(my_mutex1, my_mutex2);
std::lock_guard test(my_mutex1, std::adopt_lock);
std::lock_guard test1(my_mutex2, std::adopt_lock);
if (!msgReceive.empty())
{
cout << ++num_pop << endl;
//消息不为空
int commend = msgReceive.front();
msgReceive.pop_front();
//...其他处理
return true;
}
cout << ++num_pop << endl;
return false;
}
void outMsgRecQuene()
{
int commend = 0;
for (int i = 0; i < 100; ++i)
{
bool result = booloutMsg(commend);
if (result==true)
{
//成功处理
}
else
{
//消息为空
cout << "outMsgRecQuene执行,但是消息队列为空!" << endl;
}
}
}
};
int main()
{
A a;
std::thread myOutMsg(&A::outMsgRecQuene, &a);
std::thread myRecMsg(&A::inMsgRecQueue, &a);
myOutMsg.join();
myRecMsg.join();
cout << "num_push = " << num_push << endl
<< "num_pop = " << num_pop << endl;
return 0;
}