Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++.exe 生成活动文件",
"command": "D:\\mingw64\\bin\\g++.exe",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}
48 changes: 28 additions & 20 deletions ThreadPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,34 @@ class ThreadPool {
};

// the constructor just launches some amount of workers
inline ThreadPool::ThreadPool(size_t threads)
: stop(false)
{
for(size_t i = 0;i<threads;++i)
inline ThreadPool::// 修改后的构造函数(在 lambda 中检查 stop 标志)
ThreadPool(size_t threads) : stop(false) {
for (size_t i = 0; i < threads; ++i) {
workers.emplace_back(
[this]
{
for(;;)
{
[this] {
while (true) {
std::function<void()> task;

{
std::unique_lock<std::mutex> lock(this->queue_mutex);
this->condition.wait(lock,
[this]{ return this->stop || !this->tasks.empty(); });
if(this->stop && this->tasks.empty())
// 关键修复:等待条件同时检查 stop 和任务队列
this->condition.wait(lock, [this] {
return this->stop || !this->tasks.empty();
});

// 若 stop 且任务队列为空,退出线程
if (this->stop && this->tasks.empty()) {
return;
}

// 否则执行任务
task = std::move(this->tasks.front());
this->tasks.pop();
}

task();
task(); // 执行任务时不持有锁
}
}
);
}
}

// add new work item to the pool
Expand Down Expand Up @@ -84,15 +87,20 @@ auto ThreadPool::enqueue(F&& f, Args&&... args)
}

// the destructor joins all threads
inline ThreadPool::~ThreadPool()
{
inline ThreadPool::// 修改后的析构函数
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
stop = true; // 设置停止标志
}
condition.notify_all(); // 唤醒所有等待的线程

// 等待所有线程结束(添加 joinable 检查)
for (std::thread& worker : workers) {
if (worker.joinable()) { // 避免重复 join 导致的错误
worker.join();
}
}
condition.notify_all();
for(std::thread &worker: workers)
worker.join();
}

#endif
47 changes: 47 additions & 0 deletions test_deadlock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "ThreadPool.h"
#include <iostream>
#include <vector>
#include <atomic>
#include <chrono>

int main() {
// 测试场景1:正常析构(无任务)
{
ThreadPool pool(4);
// 立即析构,无任务执行
}
std::cout << "Test 1 passed: No deadlock when destroying empty pool." << std::endl;

// 测试场景2:提交任务后析构
{
ThreadPool pool(4);
std::atomic<int> counter(0);

// 提交大量短任务
for (int i = 0; i < 1000; ++i) {
pool.enqueue([&counter] {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
counter.fetch_add(1, std::memory_order_relaxed);
});
}

// 不等待任务完成,直接析构
}
std::cout << "Test 2 passed: No deadlock when destroying pool with pending tasks." << std::endl;

// 测试场景3:提交耗时任务后析构
{
ThreadPool pool(4);

// 提交一个长时间运行的任务
pool.enqueue([] {
std::this_thread::sleep_for(std::chrono::seconds(2));
});

// 立即析构(任务可能仍在执行)
}
std::cout << "Test 3 passed: No deadlock when destroying pool with running tasks." << std::endl;

std::cout << "All tests passed!" << std::endl;
return 0;
}
Binary file added test_deadlock.exe
Binary file not shown.