在Linux下,C++可以通过多种方式实现多线程同步。以下是一些常用的同步机制:
互斥锁(Mutexes):
std::mutex
: C++标准库提供的互斥锁,用于保护共享资源。std::lock_guard
: RAII风格的互斥锁管理类,它在构造时锁定互斥锁,在析构时自动解锁。std::unique_lock
: 提供比std::lock_guard
更灵活的锁定机制,允许延迟锁定、时间锁定等。条件变量(Condition Variables):
std::condition_variable
: 与互斥锁一起使用,允许线程等待某个条件成立。std::condition_variable_any
: 类似于std::condition_variable
,但可以与任何锁类型一起使用。读写锁(Read-Write Locks):
std::shared_mutex
: C++17引入的读写锁,允许多个读取者或一个写入者访问共享资源。std::shared_lock
: 与std::shared_mutex
配合使用,用于读取操作。原子操作(Atomic Operations):
std::atomic
: C++11引入的模板类,用于执行原子操作,保证操作的原子性,无需使用互斥锁。屏障(Barriers):
std::barrier
: C++20引入的同步原语,用于使一组线程互相等待到达某个点。信号量(Semaphores):
sem_wait
, sem_post
, sem_init
等函数来使用。下面是一个简单的例子,展示了如何使用std::mutex
和std::condition_variable
来实现线程同步:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id(int id) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) {
cv.wait(lck); // 等待条件变量
}
// 打印线程ID
std::cout << "Thread " << id << std::endl;
}
void go() {
std::lock_guard<std::mutex> lck(mtx);
ready = true; // 改变条件变量
cv.notify_all(); // 唤醒所有等待的线程
}
int main() {
std::thread threads[10];
// 创建多个线程
for (int i = 0; i < 10; ++i) {
threads[i] = std::thread(print_id, i);
}
std::cout << "10 threads ready to race..." << std::endl;
go(); // 改变条件并唤醒线程
for (auto &th : threads) {
th.join(); // 等待所有线程完成
}
return 0;
}
在这个例子中,我们创建了10个线程,它们都在等待一个条件变量cv
被通知。主线程通过调用go()
函数来改变条件变量ready
的状态,并通过cv.notify_all()
来唤醒所有等待的线程。一旦被唤醒,线程将检查条件变量ready
,如果为true
,则继续执行。
请注意,多线程编程需要小心处理同步问题,以避免死锁、竞态条件等问题。务必确保在使用共享资源时正确地锁定和解锁互斥锁,并且在适当的时候使用条件变量来同步线程。