目录
[1. 创建、管理和操作线程:std::thread](#1. 创建、管理和操作线程:std::thread)
[2. 互斥量(Mutex)](#2. 互斥量(Mutex))
[3. 锁(Lock)](#3. 锁(Lock))
[4. 条件变量(Condition Variables)](#4. 条件变量(Condition Variables))
[5. 原子操作(Atomic Operations)](#5. 原子操作(Atomic Operations))
[6. 异步任务和 Futures](#6. 异步任务和 Futures)
[使用 std::async](#使用 std::async)
[使用 std::promise 和 std::future](#使用 std::promise 和 std::future)
在现代软件开发中,多线程编程能够显著提高程序的性能和响应性。C++11 引入了许多新的特性,极大丰富了多线程编程的支持。以下将重点介绍 C++ 中的多线程相关技术,包括 std::thread
、互斥量、锁、条件变量、原子操作以及异步任务和 Futures。
1. 创建、管理和操作线程:std::thread
std::thread
是 C++11 标准库中引入的类,用于创建和管理线程。
示例
cpp
#include <iostream>
#include <thread>
void threadFunction() {
std::cout << "Thread is running!" << std::endl;
}
int main() {
// 创建线程
std::thread t(threadFunction);
// 等待线程完成
if (t.joinable()) {
t.join(); // 等待线程结束
}
std::cout << "Thread has finished." << std::endl;
return 0;
}
输出
cpp
Thread is running!
Thread has finished.
解释
std::thread
接受一个函数(或可调用对象)作为参数。- 使用
join()
函数等待线程完成,joinable()
用于检查线程是否可以被加入。
2. 互斥量(Mutex)
互斥量用于保护共享资源,防止数据竞争。C++ 提供了 std::mutex
和 std::recursive_mutex
,后者允许同一线程多次锁定。
示例
cpp
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void printMessage(int id) {
std::lock_guard<std::mutex> lock(mtx); // 自动管理锁的生命周期
std::cout << "Thread ID: " << id << std::endl;
}
int main() {
std::thread t1(printMessage, 1);
std::thread t2(printMessage, 2);
t1.join();
t2.join();
return 0;
}
输出
cpp
Thread ID: 1
Thread ID: 2
(输出顺序可能会变,因为线程的调度是非确定性的。)
解释
std::lock_guard
在其作用域内自动锁定互斥量,并在作用域结束时自动解锁。- 使用
std::recursive_mutex
可以在同一线程中多次锁定。
3. 锁(Lock)
锁提供了管理互斥量的灵活性。std::unique_lock
提供更多的功能,可以控制锁的生命周期。
示例
cpp
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void printMessage(int id) {
std::unique_lock<std::mutex> lock(mtx, std::defer_lock); // 延迟锁定
lock.lock(); // 手动锁定
std::cout << "Thread ID: " << id << std::endl;
lock.unlock(); // 提前解锁
}
int main() {
std::thread t1(printMessage, 1);
std::thread t2(printMessage, 2);
t1.join();
t2.join();
return 0;
}
输出
cpp
Thread ID: 1
Thread ID: 2
(输出顺序可能会有所不同。)
解释
std::unique_lock
提供延迟锁定和提前解锁的功能,适用于需要更复杂锁管理的情况。
4. 条件变量(Condition Variables)
条件变量用于线程间的通知和等待。它们允许线程在特定条件满足时继续执行。
示例
cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void printMessage(int id) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return ready; }); // 等待条件变量的通知
std::cout << "Thread ID: " << id << std::endl;
}
void setReady() {
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_all(); // 通知所有等待的线程
}
int main() {
std::thread t1(printMessage, 1);
std::thread t2(printMessage, 2);
setReady(); // 设置条件并通知
t1.join();
t2.join();
return 0;
}
输出
cpp
Thread ID: 1
Thread ID: 2
(两个线程会在条件满足后同时打印。)
解释
cv.wait
使线程等待直到条件满足。cv.notify_all
唤醒所有等待的线程。
5. 原子操作(Atomic Operations)
std::atomic
支持无锁编程,确保在高并发情况下的线程安全。
示例
cpp
#include <iostream>
#include <thread>
#include <atomic>
std::atomic<int> counter(0);
void incrementCounter() {
for (int i = 0; i < 1000; ++i) {
++counter; // 原子操作
}
}
int main() {
std::thread t1(incrementCounter);
std::thread t2(incrementCounter);
t1.join();
t2.join();
std::cout << "Counter: " << counter.load() << std::endl; // 获取值
return 0;
}
输出
cpp
Counter: 2000
(两个线程各自增加计数器 1000 次,总和为 2000。)
解释
std::atomic<int>
提供线程安全的整数操作,无需使用互斥量。
6. 异步任务和 Futures
C++11 提供了 std::async
、std::promise
和 std::future
,用于异步任务和线程间通信。
示例
使用 std::async
cpp
#include <iostream>
#include <future>
int asyncTask() {
std::this_thread::sleep_for(std::chrono::seconds(1));
return 42;
}
int main() {
std::future<int> result = std::async(std::launch::async, asyncTask);
std::cout << "Waiting for result..." << std::endl;
std::cout << "Result: " << result.get() << std::endl; // 阻塞直到获取结果
return 0;
}
输出
cpp
Waiting for result...
Result: 42
使用 std::promise
和 std::future
cpp
#include <iostream>
#include <thread>
#include <future>
void setPromiseValue(std::promise<int>& prom) {
std::this_thread::sleep_for(std::chrono::seconds(1));
prom.set_value(42); // 设置未来值
}
int main() {
std::promise<int> prom;
std::future<int> fut = prom.get_future();
std::thread t(setPromiseValue, std::ref(prom));
std::cout << "Waiting for result..." << std::endl;
std::cout << "Result: " << fut.get() << std::endl; // 获取结果
t.join();
return 0;
}
输出
cpp
Waiting for result...
Result: 42
解释
std::async
用于启动异步任务并返回std::future
。std::promise
和std::future
用于实现线程间的结果传递。
总结
以上介绍了 C++ 多线程编程中的重要知识点,包括线程创建、互斥量、锁、条件变量、原子操作以及异步任务和 Futures。通过合理使用这些特性,可以有效地管理并发,提高程序的运行效率和安全性。在多线程编程中,确保线程安全和良好的资源管理是非常关键的。希望这些示例对您理解 C++ 的多线程开发有所帮助。