簡體   English   中英

從不同的線程,不同的函數寫入(記錄)到同一個文件?

[英]Writing (logging) into same file from different threads , different functions?

在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()在兩個不同的類中,並且沒有辦法在它們之間有共享數據:(可遺憾的是,設計是這樣的,一個函數不能調用其他函數。

添加記錄功能。
這兩個函數都調用日志記錄功能(執行適當的鎖定)。

mutex  logMutex;
void log(std::string const& msg)
{
    RAIILock  lock(logMutex);

    // open("abc.txt");
    // write msg
    // close
}

如果你真的需要一個記錄器,不要只是通過寫入文件並使用專用的記錄器來嘗試,從而將問題從你正在編寫的代碼中分離出來。 有許多線程安全的記錄器:首先想到的是: g2log 進一步谷歌搜索,你會發現log4cplus ,討論在這里 ,即使是最低限度的一個+1

如果函數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
};

然后你可以把這個struct(a)傳遞給foo1和foo2作為void *

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

你可以為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;
}

全球化志願服務青年:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM