插件窝 干货文章 Linux下C++多线程同步怎么做

Linux下C++多线程同步怎么做

std Mutex 线程 include 341    来源:    2025-05-09

Linux下C++多线程同步方法

在Linux环境下,C++提供了多种多线程同步机制来协调线程间的执行顺序和资源共享。以下是主要的同步方法:

1. 互斥锁 (Mutex)

最基本的同步机制,用于保护共享资源。

#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';
}

2. 条件变量 (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);
    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;
}

3. 读写锁 (Shared Mutex)

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';
}

4. 原子操作 (Atomic)

对于简单的数据类型,原子操作是更高效的同步方式。

#include <atomic>

std::atomic<int> counter(0);

void increment() {
    for(int i=0; i<100000; ++i) {
        counter.fetch_add(1, std::memory_order_relaxed);
    }
}

5. 信号量 (Semaphore)

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();
}

6. 屏障 (Barrier)

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';
}

选择同步机制的考虑因素

  1. 性能需求:原子操作 > 互斥锁 > 条件变量
  2. 使用场景

    • 简单共享资源:互斥锁
    • 线程间通知:条件变量
    • 读多写少:读写锁
    • 简单计数器:原子操作
    • 复杂同步:信号量或屏障
  3. 避免死锁:按固定顺序获取锁,或使用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++标准库提供了更高级的抽象,使代码更易编写和维护。