mutex虽然可以很好地协调线程同步,互斥访问全局变量。但不慎使用,也可能会造成死锁。
下面这段代码就演示了递归访问同一把锁造成的死锁:
#include<iostream>
#include<iomanip>
using namespace std;
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>
using namespace boost;
typedef boost::mutex CMutex;
typedef boost::lock_guard<CMutex> CLockGuardMutex;
typedef boost::thread_group CThreadGroup;
CMutex oMutexGlob;//一把全局锁,千军万马来相见
void Func1(void){
cout << "Enter Func1" << endl;
CLockGuardMutex oLockGuard(oMutexGlob);
cout << "Leave Func1" << endl;
}
void Func2(void){
cout << "Enter Func2" << endl;
CLockGuardMutex oLockGuard(oMutexGlob);
cout << "Leave Func2" << endl;
Func1();//递归访问同一把锁造成死锁
}
void Run(int threadno){
static CMutex oMutexConsole;//不能共享输出,互斥访问控制台
CLockGuardMutex oLockGuard(oMutexConsole);
cout << "This is Thread" << threadno << endl;
Func2();
}
void main()
{
CThreadGroup oThreadGroup;//定义一个线程组对象
//创建线程
for(int i = 0; i < 5; i++) oThreadGroup.create_thread(boost::bind(Run, i));
//等待所有线程退出
oThreadGroup.join_all();
}
解决方案:使用boost::recursive_mutex【相当于Windows下的CS关键段,同一线程可以多次进入】。当同一个线程调用时,碰到相同已经上锁的锁时,还是可以继续往下执行。
#include<ctime>
#include<cstdio>
#include<iostream>
using namespace std;
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>
using namespace boost;
typedef boost::mutex CMutex;
typedef boost::lock_guard<CMutex> CLockGuardMutex;
typedef boost::thread_group CThreadGroup;
CMutex oMutexGlob;//一把全局锁,千军万马来相见
typedef boost::recursive_mutex CRecursiveMutex;
typedef boost::lock_guard<CRecursiveMutex> CLockGuardRecursiveMutex;
//【相当于Windows下的CS关键段,同一线程可以多次进入】
//当同一个线程调用时,碰到相同已经上锁的锁时,还是可以继续往下执行
CRecursiveMutex oRecursiveMutexGlob;
void Func1(void){
cout << "Enter Func1" << endl;
this_thread::sleep(posix_time::seconds(rand()%3));
//CLockGuardMutex oLockGuard(oMutexGlob);
CLockGuardRecursiveMutex oLockGuardRecursiveMutex(oRecursiveMutexGlob);
cout << "Leave Func1" << endl;
}
void Func2(void){
cout << "Enter Func2" << endl;
//CLockGuardMutex oLockGuard(oMutexGlob);
CLockGuardRecursiveMutex oLockGuardRecursiveMutex(oRecursiveMutexGlob);
cout << "Leave Func2" << endl;
Func1();//递归访问同一把锁造成死锁
}
void Run(int threadno){
static CMutex oMutexConsole;//不能共享输出,互斥访问控制台
CLockGuardMutex oLockGuard(oMutexConsole);
cout << "This is Thread" << threadno << endl;
Func2();
}
void main()
{
srand((unsigned)time(NULL));//设置随机数的种子
CThreadGroup oThreadGroup;//定义一个线程组对象
//创建线程
for(int i = 0; i < 5; i++) oThreadGroup.create_thread(boost::bind(Run, i));
//等待所有线程退出
oThreadGroup.join_all();
}