簡體   English   中英

無法從5個以上線程並發寫入文件C ++

[英]Cannot write concurrently to file from more than 5 threads c++

我正在for循環中啟動20個線程,以將其寫入這樣的文件:

for (FileSearcher & searcher : searchers)
{
    searcher.start([&sf](std::string & fileName, int & id)
    {
        for (int i = 1; i < 100; i++)
        {
            //sf << "T " << id << " " << fileName << i << "\n";
            std::string msg("T ");
            msg += std::to_string(id);
            msg += " ";
            msg += fileName;
            msg += std::to_string(i);;
            msg += "\n";
            sf.writeLine(msg);
        }
    });

searcher.start()函數啟動線程,該線程將執行作為參數傳遞的lambda。 sf對象擁有由線程寫入的實際文件和由sf.writeLine()中的std :: lock_guard鎖定的互斥鎖。

問題在於,只有5個線程正在同時向文件寫入數據,並且其中一個線程完成了作業之后,下一個線程開始與尚未完成的其他4個線程同時寫入文件。 依此類推,直到20個線程全部完成。

為什么會這樣呢? 難道不是所有20個線程都同時寫入文件,而不是一次寫入5個線程?

這是完整的代碼:

主要:

#include <iostream>
#include "FileSearcher.h"
#include "SafeFileStream.h"

int main()
{
SafeFileStream sf("D:\\x.txt");

//sf.writeLine("hellow");
FileSearcher searchers[20];

for (int j = 0; j < 20; j++)
{
    searchers[j].setFileName("Some file name.txt");
    searchers[j].setId(j);
}

for (FileSearcher & searcher : searchers)
{
    searcher.start([&sf](std::string & fileName, int & id)
    {
        for (int i = 1; i < 100; i++)
        {
            //sf << "T " << id << " " << fileName << i << "\n";
            std::string msg("T ");
            msg += std::to_string(id);
            msg += " ";
            msg += fileName;
            msg += std::to_string(i);;
            msg += "\n";
            sf.writeLine(msg);
        }
    });
}


for (FileSearcher & searcher : searchers)
{
    searcher.join();
}

return 0;
}

FileSearcher.h

#include <thread>
#include <string>
#include <functional>
#include <fstream>

class FileSearcher {

private:
   std::unique_ptr<std::thread> searcher;
   std::string fileName;
   std::ifstream inputFile;
   int id;

public:
   FileSearcher();
   FileSearcher(const int &, const std::string &);
   ~FileSearcher();

   void start(std::function<void(std::string &, int &)>);
   void join();
   void setFileName(const std::string &);
   void setId(const int &);
};

FileSearcher.cpp

#include "FileSearcher.h"

FileSearcher::FileSearcher() {}

FileSearcher::FileSearcher(const int & id, const std::string & fileName)
{
    this->fileName = fileName;
    this->id = id;
}

FileSearcher::~FileSearcher()
{
    if (this->searcher->joinable())
    {
        this->searcher->join();
    }
}

void FileSearcher::setFileName(const std::string & fileName)
{
    this->fileName = fileName;
}

void FileSearcher::setId(const int & id)
{
    this->id = id;
}

void FileSearcher::start(std::function<void(std::string &, int & id)>   searchingMethod)
{
    this->inputFile.open(this->fileName);
    this->searcher = std::unique_ptr<std::thread>(new    std::thread(searchingMethod, std::ref(this->fileName), std::ref(this->id)));
}

void FileSearcher::join() 
{
   if (this->searcher->joinable())
   {
       this->searcher->join();
   }
}

SafeFileStream.h

#include <fstream>
#include <string>
#include <mutex>
#include <iostream>

class SafeFileStream
{
private:
    std::ofstream outputFile;
    std::string fileName;
    std::mutex mu;
    std::unique_ptr<std::lock_guard<std::mutex>> lockGuard;
    std::unique_lock<std::mutex> uniqueLocker;
    std::unique_ptr<std::thread> safeQueueHandler;

public:
    SafeFileStream(std::string);
    SafeFileStream(SafeFileStream&&);
    ~SafeFileStream();
    template <typename T> void writeLine(T);
    template <typename T> void write(T msg);
};

SafeFileStream::SafeFileStream(std::string fileName) : fileName(fileName)
{
    this->outputFile.open(fileName);
}

SafeFileStream::SafeFileStream(SafeFileStream&& sfFileStream)
{
    this->fileName = sfFileStream.fileName;
}

SafeFileStream::~SafeFileStream()
{
    this->outputFile.close();
}

template <typename T> void SafeFileStream::writeLine(T msg)
{
    std::lock_guard<std::mutex> lockGuard(this->mu);
    this->outputFile << msg << "\n";
}

template <typename T> void SafeFileStream::write(T msg)
{
    std::lock_guard<std::mutex> lockGuard(this->mu);
    this->outputFile << msg;
}

您無法確定上下文切換的時間。 這取決於操作系統。 但是您可以“詢問”上下文切換到操作系統的情況。

調用std :: this_thread :: yield(); 在sf.writeLine(msg);之后

for (FileSearcher & searcher : searchers)
{
    searcher.start([&sf](std::string & fileName, int & id)
    {
        for (int i = 1; i < 100; i++)
        {
            //sf << "T " << id << " " << fileName << i << "\n";
            std::string msg("T ");
            msg += std::to_string(id);
            msg += " ";
            msg += fileName;
            msg += std::to_string(i);;
            msg += "\n";
            sf.writeLine(msg);
            std::this_thread::yield();
        }
    });

暫無
暫無

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

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