文章目录
- **1. 什么是线程**
- **2. C++ 中的线程库**
- **3. 创建线程**
- 基本用法
- 使用 Lambda 表达式
- 使用类成员函数
- **4. 管理线程**
- `join` 和 `detach`
- 检查线程是否可加入
- **5. 数据共享与同步**
- 数据竞争问题
- 使用互斥锁 (`std::mutex`)
- 死锁与避免
- **6. 条件变量**
- **7. 线程间通信**
- 使用 `std::future` 和 `std::promise`
- **8. 总结**
C++ 中的线程是指程序中能够独立执行的一条控制流。线程允许在同一个进程中并发运行多个任务,从而提高程序的性能和响应性。C++11 标准引入了对线程的原生支持,通过 <thread>
标准库提供了一套工具来管理线程。
1. 什么是线程
线程是程序执行的基本单位,多个线程可以共享同一进程的资源(如内存、文件句柄等)。线程的使用场景包括:
- 多任务并行处理(如同时处理用户输入和后台计算)。
- 提高程序性能(利用多核 CPU)。
- 异步操作(如非阻塞 I/O)。
2. C++ 中的线程库
C++ 标准库中的线程功能由头文件 <thread>
提供,主要包括:
std::thread
:用于创建和管理线程。std::mutex
:用于线程同步,防止数据竞争。std::condition_variable
:用于线程间的条件通知。std::future
和std::promise
:用于线程间的结果传递。
3. 创建线程
基本用法
#include <iostream>
#include <thread>void task() {std::cout << "Hello from thread!" << std::endl;
}int main() {std::thread t(task); // 创建并启动线程t.join(); // 等待线程完成return 0;
}
说明:
std::thread t(task)
:启动线程t
,执行函数task
。t.join()
:主线程等待子线程完成。如果没有调用join()
或detach()
,程序会报错。
使用 Lambda 表达式
#include <iostream>
#include <thread>int main() {std::thread t([] {std::cout << "Hello from Lambda thread!" << std::endl;});t.join();return 0;
}
使用类成员函数
#include <iostream>
#include <thread>class Task {
public:void operator()() const {std::cout << "Hello from class thread!" << std::endl;}
};int main() {Task task;std::thread t(task); // 使用类的调用运算符t.join();return 0;
}
4. 管理线程
join
和 detach
join()
:等待线程执行完成。线程执行完成前,主线程会被阻塞。detach()
:将线程与主线程分离,线程在后台继续运行。分离的线程无法再被主线程管理。
std::thread t(task);
t.detach(); // t 独立运行
检查线程是否可加入
if (t.joinable()) {t.join();
}
5. 数据共享与同步
数据竞争问题
多个线程共享数据时,可能会发生数据竞争(多个线程同时访问和修改同一资源)。
#include <iostream>
#include <thread>int counter = 0;void increment() {for (int i = 0; i < 100000; ++i) {++counter;}
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Counter: " << counter << std::endl; // 结果可能不正确return 0;
}
使用互斥锁 (std::mutex
)
互斥锁可以防止数据竞争。
#include <iostream>
#include <thread>
#include <mutex>int counter = 0;
std::mutex mtx;void increment() {for (int i = 0; i < 100000; ++i) {std::lock_guard<std::mutex> lock(mtx); // 自动管理锁++counter;}
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Counter: " << counter << std::endl; // 结果正确return 0;
}
死锁与避免
使用多个互斥锁时可能会发生死锁。可以使用 std::lock
同时锁定多个资源。
std::lock(mutex1, mutex2);
6. 条件变量
条件变量用于线程间的同步,使一个线程等待另一个线程的通知。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
bool ready = false;void worker() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return ready; }); // 等待通知std::cout << "Worker is running!" << std::endl;
}int main() {std::thread t(worker);std::this_thread::sleep_for(std::chrono::seconds(1));{std::lock_guard<std::mutex> lock(mtx);ready = true;}cv.notify_one(); // 通知线程t.join();return 0;
}
7. 线程间通信
使用 std::future
和 std::promise
std::promise
:允许线程间传递值。std::future
:用于获取异步结果。
#include <iostream>
#include <thread>
#include <future>void compute(std::promise<int> p) {p.set_value(42); // 设置结果
}int main() {std::promise<int> p;std::future<int> f = p.get_future();std::thread t(compute, std::move(p));std::cout << "Result: " << f.get() << std::endl; // 获取结果t.join();return 0;
}
8. 总结
C++ 的线程功能强大,可以用于实现高效的多任务并行处理。然而,开发多线程程序需要注意以下几点:
- 数据同步:通过
std::mutex
或其他机制避免数据竞争。 - 死锁问题:小心使用多个锁,合理设计锁的顺序。
- 资源管理:使用智能指针和
std::lock_guard
等工具确保资源安全。
正确地使用线程可以极大地提升程序的性能,但也增加了程序的复杂性和调试难度。