在Linux环境下,C++提供了多种多线程同步机制来协调线程间的执行顺序和资源共享。以下是主要的同步方法:
最基本的同步机制,用于保护共享资源。
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void print_block(int n, char c) {
mtx.lock();
for(int i=0; i<n; ++i) { std::cout << c; }
std::cout << '\n';
mtx.unlock();
}
int main() {
std::thread th1(print_block, 50, '*');
std::thread th2(print_block, 50, '$');
th1.join();
th2.join();
return 0;
}
更安全的RAII方式:
void print_block(int n, char c) {
std::lock_guard<std::mutex> guard(mtx);
for(int i=0; i<n; ++i) { std::cout << c; }
std::cout << '\n';
}
用于线程间通信,允许线程等待特定条件成立。
#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);
std::cout << "thread " << id << '\n';
}
void go() {
std::unique_lock<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...\n";
go();
for(auto& th : threads) th.join();
return 0;
}
C++17引入,允许多个读操作同时进行,但写操作是独占的。
#include <shared_mutex>
std::shared_mutex smtx;
int shared_data = 0;
void reader(int id) {
std::shared_lock<std::shared_mutex> lock(smtx);
std::cout << "Reader " << id << " sees " << shared_data << '\n';
}
void writer(int id, int value) {
std::unique_lock<std::shared_mutex> lock(smtx);
shared_data = value;
std::cout << "Writer " << id << " wrote " << value << '\n';
}
对于简单的数据类型,原子操作是更高效的同步方式。
#include <atomic>
std::atomic<int> counter(0);
void increment() {
for(int i=0; i<100000; ++i) {
counter.fetch_add(1, std::memory_order_relaxed);
}
}
C++20引入了信号量支持:
#include <semaphore>
std::counting_semaphore<10> sem(3); // 最大计数10,初始3
void worker(int id) {
sem.acquire();
std::cout << "Thread " << id << " working\n";
std::this_thread::sleep_for(std::chrono::seconds(1));
sem.release();
}
C++20引入,用于同步多个线程在某个点等待。
#include <barrier>
std::barrier sync_point(3); // 等待3个线程
void worker(int id) {
std::cout << "Before barrier " << id << '\n';
sync_point.arrive_and_wait();
std::cout << "After barrier " << id << '\n';
}
使用场景:
避免死锁:按固定顺序获取锁,或使用std::lock()
同时锁定多个互斥量
std::mutex mtx1, mtx2;
void safe_lock() {
std::lock(mtx1, mtx2); // 同时锁定,避免死锁
std::lock_guard<std::mutex> lk1(mtx1, std::adopt_lock);
std::lock_guard<std::mutex> lk2(mtx2, std::adopt_lock);
// 临界区
}
在Linux环境下,这些同步机制通常基于POSIX线程(pthread)实现,但C++标准库提供了更高级的抽象,使代码更易编写和维护。