代码来源于百度传课视频:https://chuanke.baidu.com/v3891329-172880-852300.html
注意看注释。
#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");
}
//注意,造成死锁时,shared_print函数和shared_print2函数的locker和loacker2的先后顺序是相反的,这样才能造成死锁。如果他们的先后顺序一致就不会死锁。
void shared_print(std::string id, int value)
{
std::lock_guard<std::mutex> locker(m_mutex);//如果用这种方式对资源加锁有一个好处,即万一后面的语句有异常不会导致资源一直被占用,而会自动释放资源
std::lock_guard<std::mutex> locker2(m_mutex2);
std::cout << "From" << id << ":" << value << std::endl;
}
void shared_print2(std::string id, int value)
{
std::lock_guard<std::mutex> locker2(m_mutex2);//如果主线程运行到这里,t1线程刚运行完shared_print函数的第一句。这时候t1在等待主线程释放
//mutex2,而主线程在等待t1线程释放mutex;这样就造成了死锁。
std::lock_guard<std::mutex> locker(m_mutex);//如果用这种方式对资源加锁有一个好处,即万一后面的语句有异常不会导致资源一直被占用,而会自动释放资源
std::cout << "From" << id << ":" << value << std::endl;
}
//std::ofstream& GetStream() { return f; };//这样就使得成员f暴露出去了,于是便失去了对该资源的保护
//也不能把资源当参数传递
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;
}