代码来源于百度传课:htps://chuanke.baidu.com/v3891329-172880-852300.html
总结如下:
1.评估一下程序,看看是否确实需要有两个mutex?如果只有一个mutex,就不存在死锁的问题了。
2.避免在锁住mutex的同时,去调用另外的我们不熟悉的函数,因为有可能这个函数包含了另外的锁,所以我们必须清楚我们所调用的其他的函数或者类。
3.如果确实需要在同一时间使用两个以上的mutex,那么可以使用c++标准库提供的std::lock函数,这样就可以确保mutex的顺序是相同的。在某些极端的情况下可能没法使用std::lock函数,这时候就要确保锁的先后顺序是一致的(如例子中,我们应该确保locker和locker2在两个函数shared_print和shared_print2中出现的先后顺序是一致的)。
#include <iostream>
#include <thread>
#include <mutex>
#include <string>
#include <fstream>
//std::mutex mu;
//
//void shared_print(std::string msg, int id)
//{
// //mu.lock();//若不释放则资源会被一直占用
// std::cout << msg << id << std::endl;//相当于对cout这个资源加锁,若此句出现了异常则资源将会被一直占用
// //mu.unlock();
//}
class LogFile
{
public:
LogFile()
{
f.open("log.txt");
}
void shared_print(std::string id, int value)
{
std::lock(m_mutex, m_mutex2);
std::lock_guard<std::mutex> locker(m_mutex,std::adopt_lock);//第二个参数的意思是,该mutex已经被锁住。获取mutex所有权,析构时解锁mutex
std::lock_guard<std::mutex> locker2(m_mutex2, std::adopt_lock);
std::cout << "From" << id << ":" << value << std::endl;//std::cout和f是一样的,只是为了更方便地查看结果,不用输出流f,而用cout
}
void shared_print2(std::string id, int value)
{
std::lock(m_mutex, m_mutex2);
std::lock_guard<std::mutex> locker2(m_mutex2, std::adopt_lock);
std::lock_guard<std::mutex> locker(m_mutex,std::adopt_lock);
std::cout << "From" << id << ":" << value << std::endl;
}
protected:
private:
std::mutex m_mutex;
std::mutex m_mutex2;
std::ofstream f;//资源f是类的成员,也就是说在类的保护之下。这样的话要想用资源必须要用类,这样就起到了资源和锁绑定到一起的作用
};
void Function1(LogFile& log)
{
for (int i = 0;i < 100;i++)
log.shared_print("In Funtion1", i);
}
int main()
{
LogFile log;
std::thread t1(Function1,std::ref(log));
for (int j = 0;j < 100;j++)
{
log.shared_print2( "In Main" ,j);
}
t1.join();
return 0;
}