用C++11的多线程读文件

本文探讨了在不使用锁的情况下,多个线程并行读取大文件的可能性及其正确性。通过实例演示了如何利用不同线程读取文件的不同部分,验证了这种做法的可行性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

曾经写了一篇博客做一些大数据的处理,但是其中在读取一个大文件的时候,并没有采取并行处理的方式。那么,一个大文件,为了能够批量处理,现在由多个线程来同时读它,各自读取一块(所读内容互不相同)。这么做会有问题吗?
答:如果只有读线程,那么没有问题。因为,不同的线程可以创建自己的文件描述符表项,再分别指向不同的文件表项,而每个文件表项里面可以有不同的当前文件偏移量,所以没有问题。而且这种情况也根本不需要用到锁。

以下是一个实际的例子。
首先,假设当前目录有一个文件1.txt(注意:必须是UNIX格式而非DOS格式),其内容如下:

111111111
222222222
333333333
444444444
555555555
666666666
777777777
888888888
999999999
000000000

处理代码如下:

    #include <thread>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <vector>
    #include <chrono>
    using namespace std;


    void thread_read_file(int tid, const string& file_path)
    {
        ifstream file(file_path.c_str(), ios::in);
        if (!file.good()) {
            stringstream ss;
            ss << "Thread " << tid << " failed to open file: " << file_path << "\n";
            cout << ss.str();
            return;
        }
        
        int pos; 
        if (tid == 0) pos = 0;
        else pos = tid*10; 
        
        file.seekg(pos, ios::beg);
        string line;
        getline(file, line);
        stringstream ss;
        ss << "Thread " << tid << ", pos=" << pos << ": " << line << "\n";
        cout << ss.str();
    }

    void test_detach(const string& file_path)
    {
        for (int i=0; i<10; ++i) {
            std::thread  th(thread_read_file, i, file_path);
            th.detach(); 
        }
    }

    void test_join(const string& file_path)
    {
        vector<std::thread> vec_threads;
        for (int i=0; i<10; ++i) {
            std::thread  th(thread_read_file, i, file_path);
            vec_threads.emplace_back(std::move(th));  // push_back() is also OK
        }
        
        auto it = vec_threads.begin();
        for (; it != vec_threads.end(); ++it) {
            (*it).join();
        }
    }


    int main()
    {
        string file_path = "./1.txt";
        test_detach(file_path);
        std::this_thread::sleep_for(std::chrono::seconds(1));  // wait for detached threads done
        test_join(file_path);
        return 0;
    }

以上代码中,展示了线程的detach和join的2种写法。对于本例来说,实际程序中,还是应该写成join. 道理也很简单。如果写成了detach,一旦主线程先结束了,那么还没来得及打印的detach的子线程也就再也不会打印其信息了。

(完)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值