如何在c ++ 11中多线程读取文件?

use*_*024 3 c++ multithreading mutex c++11

我有一个大文件,我必须通过块读取它.每次当我读取一个块时,我都要做一些耗时的操作,所以我认为多线程读取可能有所帮助,每个线程逐个读取一个块并进行操作.这是我在c ++ 11中的代码

#include<iostream>
#include<fstream>
#include <condition_variable>
#include <mutex>
#include <thread>
using namespace std;
const int CHAR_PER_FILE = 1e8;
const int NUM_THREAD = 2;
int order = -1;
bool is_reading = false;
mutex mtx;
condition_variable file_not_reading;
void partition(ifstream& is)
{
    while (is.peek() != EOF)
    {
        unique_lock<mutex> lock(mtx);
        while (is_reading)
            file_not_reading.wait(lock);

        is_reading = true;
        char *c = new char[CHAR_PER_FILE];

        is.read(c, CHAR_PER_FILE);
        order++;

        is_reading = false;

        file_not_reading.notify_all();
        lock.unlock();

        char oc[3];
        sprintf(oc, "%d", order);
        this_thread::sleep_for(chrono::milliseconds(2000));//some operations that take long time
        ofstream os(oc, ios::binary);
        os.write(c, CHAR_PER_FILE);
        delete[] c;
        os.close();
    }
}

int main()
{
    ifstream is("bigfile.txt",ios::binary);
    thread threads[NUM_THREAD];
    for (int i = 0; i < NUM_THREAD; i++)
        threads[i] = thread(partition, ref(is));

    for (int i = 0; i < NUM_THREAD; i++)
        threads[i].join();

    is.close();
    system("pause");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是我的代码不起作用,它只创建了4个文件而不是`bigfilesize/CHAR_PER_FILE,并且线程似乎卡住了,我怎么能让它工作?

是否有任何c ++ 11多线程读取文件实现或示例?

谢谢.

jsa*_*der 5

我的建议:

  • 使用一个线程从文件中读取块.每次读取一个块时,将其发布到请求队列.不值得阅读多线程,因为会有内部锁定/阻塞读取公共资源.
  • 使用线程池.它们中的每一个都从队列中读取,检索一个块,执行昂贵的操作并返回以等待新的请求.
  • 队列必须受互斥保护.
  • 不要使用比您拥有的处理单元(CPU /内核/超线程)数量更多的线程.
  • 上面的主要警告是它不能保证处理顺序.您可能需要将结果发布到可以重新排序的中心位置(同样是中心位置 - >必须是互斥保护的).


Jen*_*ens 5

您可以将基于任务的并行性与 std::async 结合使用:

class result; // result of expensive operation
result expensive_operation(std::vector<char> const& data)
{
 result r = // long computation
 return r;
}

std::vector<char>::size_type BLOCK_SIZE = 4096;

std::vector<std::future<result>> partition(ifstream& in)
{
    std::vector<std::future<result>> tasks;

    while (!in.eof() && !in.fail())
    {
        std::vector<char> c(BLOCK_SIZE);
        is.read(c.data(), BLOCK_SIZE);
        c.resize(in.gcount());
        tasks.push_back( std::async( [](std::vector<char> data) 
        {
            return expensive_operation(data);
        },
        std::move(c) ));
    }
    return tasks;
}

int main()
{
    ifstream is("bigfile.txt",ios::binary);
    auto results = partition(is);

    // iterate over results and do something with it
}
Run Code Online (Sandbox Code Playgroud)