我在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;
}
答案 0 :(得分:0)
您无法确定上下文切换的时间。 这取决于操作系统。 但您可以“询问”上下文切换到操作系统。
调用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();
}
});