Data 2018/11/12 Add By WJB
这次解决如何让代码在线线程中仅执行一次,这就是所谓的Lazy_initial。
看下上个程序的一段代码;
class LogFile{
public:
LogFile()
{
f.open(“logfile.txt”);
}
public:
void Print_string(string & msg,int id)
{
unique_lock <mutex> uniqelocker(m_Mutex);
f << msg <<"ID:"<<id<< endl;
}
private:
mutex m_Mutex;
mutex m_Mutex_Open;
fstream f;
};
这个代码中,在创建类时就会打开f文件,如果不调用print_string方法,那么打开f就是一个多余操作,所以在调用print_string方式时再打开。但是打开文件时要加锁,修改后代码如下;
void Print_string(string & msg,int id)
{
if (!f.is_open())
{
//打开仅执行一次所以要加锁
unique_lock <mutex> uniqelocker(m_Mutex_Open);
f.open("logfile.txt", ifstream::out | fstream::in | ifstream::app);
}
unique_lock <mutex> uniqelocker(m_Mutex);
f << msg <<"ID:"<<id<< endl;
}
这样的修改也存在一个问题,例如线程1判单文件没有打开然后加锁,在文件还没有打开前线程2又去判断f是否打开,线程2也会判断为未打开,线程2也会去加锁,这样就容易出问题。再稍作修改,修改后代码如下:
void Print_string(string & msg,int id)
{
unique_lock <mutex> uniqelocker(m_Mutex_Open);
{
if (!f.is_open())
{
f.open("logfile.txt", ifstream::out | fstream::in | ifstream::app);
}
}
unique_lock <mutex> uniqelocker(m_Mutex);
f << msg << "ID:" << id << endl;
}
这样修改就避免了多个线程打开文件,但是这样的话就会用到很多m_mutex_open 锁,造成巨大的资源浪费,所以这里就用到了一个单次使用的对象std::once_flag;使用方法如下
std::once_flag m_flag;
void Print_string(string & msg,int id)
{
std::call_once(m_flag ,[&](){ f.open("logfile.txt"); });//lamda 表达式
unique_lock <mutex> uniqelocker(m_Mutex);
f << msg << "ID:" << id << endl;
}
这样就确保了f这个lamda表达式只被一个线程执行一次。
全部代码:
#include <thread>
#include <iostream>
#include <string.h>
#include <string>
#include <mutex>
#include <fstream>
using namespace std;
class LogFile{
public:
LogFile()
{
}
~LogFile()
{
if (f.is_open())
{
f.close();
}
}
public:
void Print_string(string & msg,int id)
{
std::call_once(m_flag ,[&](){ f.open("logfile.txt"); });//lamda 表达式
unique_lock <mutex> uniqelocker(m_Mutex);
f << msg << "ID:" << id << endl;
}
private:
mutex m_Mutex;
std::once_flag m_flag;
//mutex m_Mutex_Open;
fstream f;
};
void Function_1(LogFile& logfile)
{
for (int i = 0; i > -100; i--)
{
string str = "my name is multithread!\n";
logfile.Print_string(str, i);
}
}
int main()
{
LogFile logfile;
thread mythread(Function_1,std::ref(logfile));
for (int i = 0; i <100; i++)
{
string str = "this is mainthread!\n";
logfile.Print_string(str,i);
}
mythread.join(); //阻塞式
return 0;
}
上一篇连接:https://blog.csdn.net/wangjianbo09/article/details/83990550