多线程统计文件单词数:chunkSize≥2时程序报错求助
多线程单词统计程序的问题修复
问题分析
你的代码没法实现并行计算,还会在chunkSize≥2时触发报错,核心问题有这几个:
- 锁的使用完全错误:线程
t1启动后直接锁住互斥量,直到整个分块流程结束才解锁,导致t2全程阻塞,完全没有并行执行的效果,和单线程运行没区别。 - t2的循环逻辑错误:你用
i < chunkSize作为循环终止条件,这会只处理前chunkSize个分块,但实际分块数量是总行数/chunkSize向上取整——比如总共有10行、chunkSize=2时,分块数是5,你只处理前2个会漏统计;如果总行数少于chunkSize,还会直接访问不存在的chunks[i],触发数组越界报错。 - 线程执行顺序未同步:
t2可能在t1还没生成完分块时就去读取chunks,此时chunks内的元素还未填充,同样会引发越界访问。
修复方案
重新设计逻辑:主线程先完成文件读取和分块操作,再启动多个线程并行处理不同分块,用互斥量保护全局结果的累加过程,确保线程安全。
修复后的代码:
#include<iostream> #include<fstream> #include <mutex> #include <thread> #include <sstream> #include <vector> std::mutex result_mutex; unsigned long long total_res = 0; int countWords(const std::string& str) { std::stringstream ss(str); std::string word; int count = 0; while (ss >> word) { count++; } return count; } // 统计单个分块的单词数,并安全累加至全局结果 void countChunkWords(const std::vector<std::string>& chunk) { int chunk_count = 0; for (const auto& line : chunk) { chunk_count += countWords(line); } // 用lock_guard自动管理锁,避免死锁 std::lock_guard<std::mutex> lock(result_mutex); total_res += chunk_count; } int main() { char pat[100]; std::cin >> pat; std::ifstream fin(pat); if (!fin.is_open()) { std::cerr << "打开文件失败。" << std::endl; return 1; } std::vector<std::string> textSplit; std::string line; while (std::getline(fin, line)) { textSplit.push_back(line); } fin.close(); std::cout << "输入分块大小: "; size_t chunkSize{}; std::cin >> chunkSize; size_t totalLength = textSplit.size(); std::vector<std::vector<std::string>> chunks; // 主线程完成分块,无需额外线程处理 for (size_t i = 0; i < totalLength; i += chunkSize) { auto start = textSplit.begin() + i; auto end = textSplit.begin() + std::min(i + chunkSize, totalLength); chunks.emplace_back(start, end); } // 创建线程,每个线程负责一个分块的统计 std::vector<std::thread> threads; for (const auto& chunk : chunks) { threads.emplace_back(countChunkWords, std::ref(chunk)); } // 等待所有线程执行完成 for (auto& t : threads) { t.join(); } std::cout << "\n总单词数: " << total_res << std::endl; return 0; }
关键修改点
- 分块逻辑移至主线程:分块是简单的数组分割操作,主线程处理即可,无需额外线程。
- 线程分工明确:启动与分块数量一致的线程,每个线程独立统计对应分块的单词数,真正实现并行计算。
- 正确使用锁:仅在累加全局结果时加锁,用
std::lock_guard自动管理锁的生命周期,避免死锁风险。 - 修正循环逻辑:遍历所有分块进行统计,确保文件内容被完整计算。
内容的提问来源于stack exchange,提问作者swizy
相关产品推荐
相关产品推荐

