【问题标题】:C++ - How to have multiple threads write to a fileC++ - 如何让多个线程写入文件
【发布时间】:2015-11-08 17:37:45
【问题描述】:

我目前正在编写一个使用线程将字符串写入文件的 c++ 程序。我正在使用 ofstream 编写这些字符串,我注意到只有一个线程可以访问该文件。

所以我的问题是:有没有办法在不同的线程中使用 ofstream 来写入同一个文件?

如果可能的话,任何例子都会很棒。如果没有,也请告诉我,一些解决这个问题的方法会很棒。 我查看了以下链接,但它对我来说并没有什么意义: Can multiple threads write into a file simultaneously, if all the threads are writing to different locations?

【问题讨论】:

  • 通常 IO 是多线程的瓶颈。通常不希望让多个线程写入同一个文件。你可以使写作同步,但此时你并没有得到想要的效果。
  • @Zboson 根据我对 btrfs 的了解,它基于 b-trees,因此无论如何它都不会线性访问数据。但是,文件系统不会写入同一个文件——它们会写入同一个系统中的多个文件,因此您可以实现一些操作加速。

标签: c++ string multithreading file ofstream


【解决方案1】:

一种方法是创建一个包装文件的对象,然后将对该包装对象的引用提供给需要写入文件的所有对象。在这个包装类中,对文件的写入是同步的,因此一次只有一个写入者可以提交要写入的数据(即,一个写入者将在另一个写入者之前完成,或者同一个写入者可以写入)。例如:

class SynchronizedFile {
public:
    SynchronizedFile (const string& path) : _path(path) {
        // Open file for writing...
    }

    void write (const string& dataToWrite) {
        // Write to the file in a synchronized manner (described below)...
    }

private:
    string _path;
};

class Writer {
public:
    Writer (std::shared_ptr<SynchronizedFile> sf) : _sf(sf) {}

    void someFunctionThatWritesToFile () {
        // Do some work...
        _sf->write("Some data to write...");
    }
private:
    std::shared_ptr<SynchronizedFile> _sf;
};

使用这些编写器的客户端代码如下所示:

// Create the synchronized file
auto synchronizedFile = std::make_shared<SynchronizedFile>("some/file.txt");

// Create the writers using the same synchronized file
Writer writer1(synchronizedFile);
Writer writer2(synchronizedFile);

使用这种方法,单个对象(SynchronizedFile 类型)管理文件,所有写入都通过该对象进行管理。现在,为了保证只有一个线程可以使用write(const string&amp;),一个std::lock_guard。使用这种锁定机制,SynchronizedFile 的实现类似于:

class SynchronizedFile {
public:
    SynchronizedFile (const string& path) : _path(path) {
        // Open file for writing...
    }

    void write (const string& dataToWrite) {
        // Ensure that only one thread can execute at a time
        std::lock_guard<std::mutex> lock(_writerMutex);

        // Write to the file...
    }

private:
    string _path;
    std::mutex _writerMutex;
};

由于看起来写入文件不是您的问题,因此我将打开和写入留给您来实现,但上面的 sn-p 显示了同步写入的基本结构。如果您在打开和写入文件时遇到问题,请告诉我,我可以为您清除。

注意:以上 sn-ps 使用 C++11 结构。如果您不能使用 C++11,请告诉我,我们可以考虑使用 C++98(或其他库/API)来实现相同的结果。

【讨论】:

  • 这里我没有看到任何线程或者我错过了什么?比如在不同的线程中启动 write 或 writer 类函数。
  • @user3792685 正确。以上不包括线程本身。相反,SynchronizedFile 类只是显示了如何包装文件,以便多个线程可以使用它而不会导致线程争用。为了清楚起见,将SynchronizedFile 对象注入单独线程的任务被省略了。
【解决方案2】:

让多个线程写入同一个文件会导致一些严重的问题。您可以尝试通过使用临界区来同步写入过程,例如(使用 OpenMP):

#pragma omp critical [(name)]
{
   write_to_file
}

或使用 WinApi: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686908(v=vs.85).aspx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    相关资源
    最近更新 更多