读取两个文件并使用线程输出到另一个文件
Reading two files and outputting to another file using threads
我的程序读入两个输入文件,并交替向输出文件写入行。我有它,所以它按正确的顺序写入(第一个文件,第二个,然后再第一个,…),但问题是它在每个文件的最后两次写入最后一个字符。
#include <iostream>
#include <fstream>
#include <thread>
#include <mutex>
using namespace std;
mutex mtx;
int turn = 1;
void print_line(ifstream * in_stream, ofstream * out_stream, int t);
int main(int argc, const char * argv[]){
ifstream input_file_1;
ifstream input_file_2;
ofstream output_file;
input_file_1.open("input_1");
input_file_2.open("input_2");
output_file.open("output");
if (input_file_1.fail() || input_file_2.fail() || output_file.fail()) {
cout << "Error while opening the input filesn";
exit(EXIT_FAILURE);
}
else{
thread input1 (print_line, &input_file_1, &output_file, 1);
thread input2 (print_line, &input_file_2, &output_file, 2);
input1.join();
input2.join();
}
input_file_1.close();
input_file_2.close();
output_file.close();
return 0;
}
void print_line(ifstream * in_stream, ofstream * out_stream, int t){
char temp;
while (!in_stream->eof()) {
mtx.lock();
if (turn == t) {
*in_stream>>temp;
*out_stream<<temp;
if (turn == 1) {
turn = 2;
}
else{
turn = 1;
}
}
mtx.unlock();
}
}
输入1
a
c
e
输入2
b
d
f
输出
abcdefef
我不知道为什么它会再次写入最后一个字符,还有没有更好的方法可以使用线程来完成排序部分,我知道互斥锁是用来确保两个线程不会同时写入的,但是我如何保证线程1在线程2之前执行,并确保它保持交替
感谢
从std::ifstream
读取直到达到EOF的正确且惯用的方法是:
char temp;
while(in_stream >> temp) {
// Will only be entered if token could be read and not EOF.
}
与此相比假设除最后一个字符外的所有字符都已从流中读取:
while(!in_stream.eof()) {
in_stream >> temp; // 1st iteration: reads last character, STILL NOT EOF.
// 2nd iteration: tries to read but reaches EOF.
// Sets eof() to true. temp unchanged.
// temp still equal to last token read.
// Continue to next statement...
/* More statements */
}
其次,您的函数print_line
在同步方面存在一些问题。解决这个问题的一种方法是使用std::condition_variable
。这里有一个例子:
condition_variable cv;
void print_line(ifstream& in_stream, ofstream& out_stream, int t){
char temp;
while (in_stream >> temp) {
unique_lock<mutex> lock(mtx); // Aquire lock on mutex.
// Block until notified. Same as "while(turn!=t) cv.wait(lock)".
cv.wait(lock, [&t] { return turn == t; });
out_stream << temp;
turn = (turn == 1) ? 2 : 1;
cv.notify_all(); // Notify all waiting threads.
}
}
正如您在上面的例子中看到的,我还将流作为引用而不是指针传递。传递指针很容易出错,因为可以传递nullptr
(NULL值)。
要将流作为引用传递给std::thread
的构造函数,必须将它们包装在引用包装器std::ref
中,例如:(std::thread
的ctor复制参数)
thread input1(print_line, ref(input_file_1), ref(output_file), 1);
实时示例(略微修改为使用标准IO而非fstream
)
其他一些东西:
1.main
:中的不必要代码
ifstream input_file_1;
ifstream input_file_2;
ofstream output_file;
input_file_1.open("input_1");
input_file_2.open("input_2");
output_file.open("output");
在此处使用直接获取文件名的构造函数,而不是使用open
:
ifstream input_file_1("input_1");
ifstream input_file_2("input_2");
ofstream output_file("output");
2.使用惯用方法检查流是否准备好读取:
if (!input_file_1 || !input_file_2 || !output_file) {
3。在这种情况下不需要使用close
,因为dtor将关闭资源(依赖RAII)。
input_file_1.close(); //
input_file_2.close(); // } Unnecessary
output_file.close(); // /
4.您的设计有些糟糕,因为进一步访问main
函数中的任何流或turn
都会导致数据竞争。
(5.)最好不要用using namespace std
污染命名空间,而是在所有地方使用完全限定的名称(例如std::ifstream
)。可选择在相关范围内声明using std::ifstream
等。
关于锁:只在进行输出时锁定,以减少锁争用和切换turn
变量。
除此之外,在我看来,这是一个非常可怕的设计。我甚至不确定C++流是否可以以这种方式跨线程使用,但即便如此,我也怀疑这是否是个好主意。
- boost::文件系统::recursive_directory_iterator多线程安全
- 两个线程一个使用流 Api,另一个线程创建文件失败并出现错误ERROR_SHARING_VIOLATION
- 在C++中写入来自不同线程的文件
- 线程 1 从文件读取,就像线程 2 写入同一文件一样
- 多个线程/进程是否可以在不同步的情况下同时从/写入文件的非重叠区域?
- 多线程和共享资源:使用C++定期将数据从缓冲区(数据结构)复制到文件
- C++中的多线程文件哈希
- C++:如何在线程中读取二进制文件并将其写入另一个线程?
- 在Qt中使用工作线程将数据写入文件的正确方法是什么?
- 我们是否需要互斥锁来执行多线程文件 IO
- Borland C++ 5.02 中使用第三方头文件的多线程
- 多线程文件 IO 程序在线程数增加时行为不可预测
- 多线程存储到文件中
- 线程1:EXC_BAD_ACCESS错误,此错误在第一行的CPP文件中的句柄函数中出现
- c++:写入多线程程序中的文件
- 多线程文件读取为每个线程生成相同的结果
- 通过多线程处理确定每个字符在文件中出现的次数
- fopen 和 fwrite 从多个线程到同一个文件
- Cmake找不到boost库文件,线程,date_time,iostreams,system
- c++多线程读取文件