从不同的线程、不同的函数写入(记录)同一文件? 在下面的场景中,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一起使用(因为它是缓冲的)从不同的线程、不同的函数写入(记录)同一文件? 在下面的场景中,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); },c++,multithreading,file,logging,C++,Multithreading,File,Logging,在我的应用程序(多线程)中,foo_one()和foo_two()可能由两个不同的线程同时执行。 有没有办法使上述线程安全 我考虑过使用文件锁(fcntl和/或lockf),但不确定如何使用它们,因为应用程序中使用了fopen()(性能原因),并且在某个地方声明这些文件锁不应与fopen一起使用(因为它是缓冲的) PS:函数foo_one()和foo_two()位于两个不同的类中,它们之间无法共享数据:(,遗憾的是,这种设计使得一个函数无法调用另一个函数。如果函数的本质是foo_one()和fo
PS:函数foo_one()和foo_two()位于两个不同的类中,它们之间无法共享数据:(,遗憾的是,这种设计使得一个函数无法调用另一个函数。如果函数的本质是
foo_one()
和foo_two()
只需打开文件,向其中写入内容,然后关闭文件,然后使用相同的互斥锁以防止它们相互干扰:
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);
}
当然,这假设只有这些写入程序。如果其他线程或进程写入该文件,最好使用锁定文件。您应该这样做,使用一个带互斥体和ofstream的结构:
struct parser {
ofstream myfile
mutex lock
};
然后您可以将这个结构(a)作为一个void传递给foo1和foo2*
parser * 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);
}
void foo_one(void*a){
parser*b=reinterperet_cast(a);
锁定(b->lock);
b->myfile.open(“abc.txt”);
//写入文件
b->myfile.close();
解锁(b->mutex);
}
您也可以对foo_two函数执行同样的操作。这将提供一种线程安全的方法来写入同一个文件。如果您真的需要一个日志记录程序,请不要尝试简单地写入文件,或者使用一个专用的日志记录程序,从而将关注点与您正在编写的代码分开。有许多线程安全的日志记录程序:第一个我想到的一点是:。在谷歌上进一步搜索,你会发现一个讨论,甚至一个,添加一个日志功能。
这两个函数都调用日志函数(执行相应的锁定)
试试这段代码。我已经用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;
}
#包括“stdafx.h”
#包括
CWinApp-theApp;
使用名称空间std;
const int size_=100;//线程数组大小
std::mutex mymutex;
无效printRailLock(内部id){
printf(“#ID:%”,ID);
LoCuxGueldLK(MyTutEx);/或:是的。你只需要一个表示文件的锁(称为MutEx3)。PS.如果你正在编写C++代码,你应该使用RAII来锁定/解锁这些互斥。@ LokistaLi函数FooSoOne()和FooYouToWo()在两个不同的类中,并且没有办法在它们之间共享资源:(,遗憾的是,设计是这样的,一个函数不能调用另一个函数。只能进行“写入”一个类的函数,在它自己的线程上被调用。循环直到它退出。然后每次你需要写一些东西到文件中,你可以把它推到向量中,让线程一到就把它写到文件中。相关:不幸的是,函数foo_one()和foo_two()在两个不同的类中,它们之间没有共享数据的方法。@k0n3ru那么锁文件的想法呢?这里有一个问题描述了该方法:虽然这种方法“有效”,而且您的答案写得很好,但您只需要知道如何使用RAII跟踪互斥体。如果ce是一个问题,锁定可能不是k0n3ru可能想要的。@DevPSEMK:它是对使用RAII
锁定/解锁另一个对象的类的一般引用。它们很容易编写。例如
#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;
}