在C ++中,有什么方法可以在以下场景中使写入文件线程安全吗?
void foo_one(){
lock(mutex1);
//open file abc.txt
//write into file
//close file
unlock(mutex1);
}
void foo_two(){
lock(mutex2);
//open file abc.txt
//write into file
//close file
unlock(mutex2);
}
在我的应用程序(多线程)中,foo_one()和foo_two()很可能同时由两个不同的线程执行。 有没有办法让上面的线程安全?
我考虑过使用文件锁(fcntl和/或lockf),但不确定如何使用它们,因为fopen()已在应用程序中使用(性能原因),并且在某处说明了那些文件锁应该不能与fopen一起使用(因为它是缓冲的)
PS:函数foo_one()和foo_two()在两个不同的类中,并且没有办法在它们之间有共享数据:(可遗憾的是,设计是这样的,一个函数不能调用其他函数。 / p>
答案 0 :(得分:8)
添加记录功能 这两个函数都调用日志记录功能(执行适当的锁定)。
mutex logMutex;
void log(std::string const& msg)
{
RAIILock lock(logMutex);
// open("abc.txt");
// write msg
// close
}
答案 1 :(得分:2)
如果您确实需要记录器,请不要仅仅通过写入文件并使用专用记录器来尝试,从而将问题与您正在编写的代码分开。有许多线程安全的记录器:第一个想到的记录器:g2log。谷歌搜索进一步你会发现log4cplus,讨论here,甚至是minimalist one,+1
答案 2 :(得分:1)
如果函数foo_one()
和foo_two()
的本质只是打开文件,写一些东西并关闭它,然后使用相同的互斥锁防止它们相互搞乱:< / p>
void foo_one(){
lock(foo_mutex);
//open file abc.txt
//write into file
//close file
unlock(foo_mutex);
}
void foo_two(){
lock(foo_mutex);
//open file abc.txt
//write into file
//close file
unlock(foo_mutex);
}
当然,这假设这些是唯一的作家。如果其他线程或进程写入文件,锁定文件可能是个好主意。
答案 3 :(得分:1)
你应该这样做,有一个带有互斥的结构和一个ofstream:
struct parser {
ofstream myfile
mutex lock
};
然后你可以将这个结构(a)作为void *
传递给foo1和foo2parser * a = new parser();
初始化互斥锁,然后你可以将结构传递给两个函数。
void foo_one(void * a){
parser * b = reinterperet_cast<parser *>(a);
lock(b->lock);
b->myfile.open("abc.txt");
//write into file
b->myfile.close();
unlock(b->mutex);
}
你可以为foo_two函数做同样的事情。这将提供一种线程安全的方法来写入同一个文件。
答案 4 :(得分:0)
试试这段代码。我已经使用 MFC控制台应用程序
完成了这项工作#include "stdafx.h"
#include <mutex>
CWinApp theApp;
using namespace std;
const int size_ = 100; //thread array size
std::mutex mymutex;
void printRailLock(int id) {
printf("#ID :%", id);
lock_guard<std::mutex> lk(mymutex); // <- this is the lock
CStdioFile lastLog;
CString logfiledb{ "_FILE_2.txt" };
CString str;
str.Format(L"%d\n", id);
bool opend = lastLog.Open(logfiledb, CFile::modeCreate | CFile::modeReadWrite | CFile::modeNoTruncate);
if (opend) {
lastLog.SeekToEnd();
lastLog.WriteString(str);
lastLog.Flush();
lastLog.Close();
}
}
int main()
{
int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(nullptr);
if (hModule != nullptr)
{
if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
{
wprintf(L"Fatal Error: MFC initialization failed\n");
nRetCode = 1;
}
else
{
std::thread threads[size_];
for (int i = 0; i < size_; ++i) {
threads[i] = std::thread(printRailLock, i + 1);
Sleep(1000);
}
for (auto& th : threads) { th.hardware_concurrency(); th.join(); }
}
}
else
{
wprintf(L"Fatal Error: GetModuleHandle failed\n");
nRetCode = 1;
}
return nRetCode;
}
<强>全球化志愿服务青年:强>