基本线程操作
1. 创建线程
#include <iostream>
#include <thread>void threadFunc() {std::cout << "子线程正在执行..." << std::endl;
}int main() {std::thread t(threadFunc); // 创建并启动线程std::cout << "主线程等待子线程..." << std::endl;t.join(); // 主线程阻塞,等待 t 执行完毕std::cout << "子线程已结束,主线程继续。" << std::endl;return 0;
}
-
t.join() 会阻塞当前线程(通常是主线程或调用 join 的线程),直到线程 t 执行完毕。
-
调用 join() 后,主线程会暂停,等待子线程 t 完成任务后才会继续执行。
关键点
-
同步线程:确保主线程等待子线程完成后再继续或退出。
-
资源清理:join() 会释放线程 t 的系统资源(如线程 ID、栈内存等)。
-
必须调用:如果线程对象 t 是 joinable 的(即已关联线程且未 join 或 detach),在销毁前必须调用 join() 或 detach(),否则程序会调用 std::terminate() 终止。
注意事项
-
如果忘记调用 join() 或 detach(),程序会异常终止。
-
不能对同一个线程多次调用 join()(会导致 std::system_error)。
-
可以通过 t.joinable() 检查线程是否需要 join。
对比 detach()
-
t.detach():分离线程,让线程独立运行,主线程不再等待(失去对线程的控制权)。
-
t.join():等待线程结束,保持控制权。
2. 带参数的线程函数
void printMessage(const std::string& message) {std::cout << message << std::endl;
}int main() {std::thread t(printMessage, "Hello from thread with args!");t.join();return 0;
}
3. 分离线程
std::thread t(backgroundTask);
t.detach(); // 线程将独立运行,主线程不再等待
线程同步
1. 互斥锁(Mutex)
作用:防止多个线程同时访问共享资源,确保同一时间只有一个线程可以访问临界区(Critical Section)。
C++ 标准库支持:std::mutex, std::lock_guard, std::unique_lock
#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx; // 全局互斥锁
int shared_data = 0;void increment() {std::lock_guard<std::mutex> lock(mtx); // 自动加锁,离开作用域解锁shared_data++; // 临界区
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Shared data: " << shared_data << std::endl; // 输出 2return 0;
}
-
std::lock_guard 是 RAII 风格锁,自动管理锁的生命周期。
-
std::unique_lock 更灵活,支持手动 lock() 和 unlock()。
2. 条件变量(Condition Variable)
作用:让线程等待某个条件成立,避免忙等待(Busy Waiting),通常与互斥锁配合使用。
C++ 标准库支持:std::condition_variable
成员函数:
- wait(lock, predicate) :阻塞当前线程,直到被唤醒且 predicate 返回 true(防止虚假唤醒)。
- notify_one() :随机唤醒一个等待的线程。
- notify_all() :唤醒所有等待的线程。
#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; }); // 等待 ready == truestd::cout << "Worker thread is processing..." << std::endl;
}int main() {std::thread t(worker);{ std::lock_guard<std::mutex> lock(mtx);ready = true; // 修改条件}cv.notify_one(); // 通知等待的线程t.join();return 0;
}
-
cv.wait() 会释放锁并进入等待状态,直到被 notify_one() 或 notify_all() 唤醒。
-
防止虚假唤醒(Spurious Wakeup),通常搭配 while 或 predicate 检查条件。
3. 原子操作(Atomic Operations)
作用:对基本数据类型(如 int, bool)提供无锁(Lock-Free)的线程安全操作。
C++ 标准库支持:std::atomic<T>
#include <iostream>
#include <thread>
#include <atomic>std::atomic<int> counter(0);void increment() {counter++; // 原子操作,无需锁
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Counter: " << counter << std::endl; // 输出 2return 0;
}
4. 读写锁(Read-Write Lock)
作用:允许多个线程同时读,但写操作独占资源(适用于读多写少的场景)。
C++ 标准库支持:std::shared_mutex(C++17)
#include <iostream>
#include <thread>
#include <shared_mutex>std::shared_mutex rw_mutex;
int data = 0;void reader() {std::shared_lock<std::shared_mutex> lock(rw_mutex); // 共享读锁std::cout << "Read data: " << data << std::endl;
}void writer() {std::unique_lock<std::shared_mutex> lock(rw_mutex); // 独占写锁data++;
}int main() {std::thread readers[3] = {std::thread(reader), std::thread(reader), std::thread(reader)};std::thread writer_thread(writer);for (auto& t : readers) t.join();writer_thread.join();return 0;
}
-
读锁(shared_lock)允许多线程并发读。
-
写锁(unique_lock)独占资源,阻塞所有读写操作。
5. 信号量(Semaphore)
作用:控制同时访问资源的线程数量(C++20 引入 std::counting_semaphore)。
#include <iostream>
#include <thread>
#include <semaphore>std::counting_semaphore<5> sem(5); // 允许最多 5 个线程同时访问void worker(int id) {sem.acquire(); // 获取信号量std::cout << "Thread " << id << " is working..." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));sem.release(); // 释放信号量
}int main() {std::thread threads[10];for (int i = 0; i < 10; i++) {threads[i] = std::thread(worker, i);}for (auto& t : threads) t.join();return 0;
}
- 适用于限流场景(如线程池、数据库连接池)。
6. 屏障(Barrier)
作用:让多个线程在某个点同步,等待所有线程到达后再继续(C++20 引入 std::barrier)。
#include <iostream>
#include <thread>
#include <barrier>std::barrier sync_point(3); // 等待 3 个线程void worker(int id) {std::cout << "Thread " << id << " started" << std::endl;sync_point.arrive_and_wait(); // 等待其他线程std::cout << "Thread " << id << " continued" << std::endl;
}int main() {std::thread t1(worker, 1);std::thread t2(worker, 2);std::thread t3(worker, 3);t1.join(); t2.join(); t3.join();return 0;
}
- 适用于分阶段并行计算(如 MapReduce)。
总结
同步方式 | 适用场景 | C++ 标准支持 |
---|---|---|
互斥锁(Mutex) | 保护共享数据,避免竞态条件 | C++11 |
条件变量 | 线程间事件通知(生产者-消费者模型) | C++11 |
原子操作 | 简单变量的无锁操作 | C++11 |
读写锁 | 读多写少的场景 | C++17 |
信号量 | 限流(如线程池) | C++20 |
屏障 | 多线程分阶段同步 | C++20 |