Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从不同的线程、不同的函数写入(记录)同一文件? 在下面的场景中,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 - Fatal编程技术网

从不同的线程、不同的函数写入(记录)同一文件? 在下面的场景中,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++中有没有办法将文件写入文件线程安全? 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

在我的应用程序(多线程)中,foo_one()和foo_two()可能由两个不同的线程同时执行。 有没有办法使上述线程安全

我考虑过使用文件锁(fcntl和/或lockf),但不确定如何使用它们,因为应用程序中使用了fopen()(性能原因),并且在某个地方声明这些文件锁不应与fopen一起使用(因为它是缓冲的)


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;
}