商城首页欢迎来到中国正版软件门户

您的位置:首页 >Linux下C++如何处理多线程同步

Linux下C++如何处理多线程同步

  发布于2026-05-02 阅读(0)

扫一扫,手机访问

Linux下C++多线程同步:从互斥锁到屏障的实战指南

在Linux平台上用C++搞多线程开发,线程同步是个绕不开的核心议题。处理不好,数据竞争、死锁这些“坑”随时可能出现。那么,有哪些趁手的同步工具可供选择呢?它们的典型用法又是怎样的?

Linux下C++如何处理多线程同步

下面,我们就来梳理几种C++标准库中常用的线程同步机制,并配上直观的代码示例。

1. 互斥锁(Mutex)

这大概是大家最熟悉的同步原语了。它的职责非常明确:保护共享资源,确保同一时刻只有一个线程能访问它,相当于给临界区上了一把独占的锁。

#include 
#include 
#include 

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

看这段代码,两个线程都想往控制台打印字符。如果没有互斥锁,输出可能会混杂在一起。而mtx.lock()mtx.unlock()这对操作,就保证了每个线程的打印区块是完整的。

2. 递归互斥锁(Recursive Mutex)

普通互斥锁有个限制:同一个线程不能重复上锁,否则会立刻导致死锁。但有些场景下,我们可能需要函数递归调用,或者一个公共函数本身就需要加锁。这时候,递归互斥锁就派上用场了。

#include 
#include 
#include 

std::recursive_mutex mtx; // 定义一个递归互斥锁

void print_block(int n, char c) {
    mtx.lock(); // 加锁
    if (n > 0) {
        std::cout << c;
        mtx.lock(); // 再次加锁
        print_block(n - 1, c);
        mtx.unlock(); // 解锁
    }
    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;
}

注意看,在递归函数print_block内部,同一个线程对mtx执行了多次lock()。如果换成普通的std::mutex,程序就会卡住。而std::recursive_mutex允许这种行为,只要确保加锁和解锁的次数匹配即可。

3. 条件变量(Condition Variable)

互斥锁解决了互斥访问的问题,但线程间有时需要“等待某个条件成立”。比如,一个线程要等队列非空才能取数据,另一个线程放入数据后需要通知它。这就是条件变量的典型应用场景。

#include 
#include 
#include 
#include 

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id(int id) {
    std::unique_lock lck(mtx);
    cv.wait(lck, []{return ready;}); // 等待条件变量
    std::cout << "Thread " << id << '\n';
}

void go() {
    std::lock_guard 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::this_thread::sleep_for(std::chrono::seconds(1)); // 等待一段时间
    go(); // 通知线程开始执行
    for (auto& th : threads) {
        th.join();
    }
    return 0;
}

这个例子展示了经典的“等待-通知”模式。10个线程启动后都在条件变量cv上等待,直到主线程调用go()ready置为true并发出notify_all()信号,所有等待的线程才继续执行。cv.wait()的第二个参数是一个谓词(lambda表达式),它避免了虚假唤醒,是更健壮的写法。

4. 读写锁(Reader-Writer Lock)

对于“读多写少”的共享数据,使用互斥锁会限制并发性能,因为读操作之间本可以不互斥。读写锁(C++17起为std::shared_mutex)应运而生,它允许多个读线程同时持有锁,但写线程独占锁。

#include 
#include 
#include 

std::shared_mutex rw_mtx; // 定义一个读写锁
int shared_data = 0;

void read_data() {
    std::shared_lock lck(rw_mtx); // 读锁
    std::cout << "Read data: " << shared_data << '\n';
}

void write_data(int value) {
    std::unique_lock lck(rw_mtx); // 写锁
    shared_data = value;
    std::cout << "Write data: " << shared_data << '\n';
}

int main() {
    std::thread readers[5];
    std::thread writer(write_data, 42);
    for (auto& th : readers) {
        th = std::thread(read_data);
    }
    for (auto& th : readers) {
        th.join();
    }
    writer.join();
    return 0;
}

使用时要注意区分:读操作使用std::shared_lock,写操作使用std::unique_lock。这样,多个read_data线程可以并发执行,而write_data线程执行时,所有读写线程都必须等待。

5. 屏障(Barrier)

最后来看看屏障。它的概念很简单:设置一个同步点,要求指定数量的线程都到达这个点后,大家才能一起继续往下执行。这在分阶段并行计算的场景中非常有用。

#include 
#include 
#include 
#include 

std::barrier sync_point(3); // 定义一个屏障,等待3个线程

void do_work(int id) {
    std::cout << "Thread " << id << " is working\n";
    sync_point.arrive_and_wait(); // 等待其他线程
    std::cout << "Thread " << id << " has passed the barrier\n";
}

int main() {
    std::vector threads;
    for (int i = 0; i < 3; ++i) {
        threads.emplace_back(do_work, i);
    }
    for (auto& th : threads) {
        th.join();
    }
    return 0;
}

代码中,屏障sync_point被设置为需要等待3个线程。每个线程完成自己的“工作”阶段后,调用arrive_and_wait(),直到另外两个线程也到达此处,三个线程才会同时继续执行“通过屏障后”的代码。

以上就是C++中几种主流的线程同步机制。简单总结一下:互斥锁是基础,递归互斥锁解决特定嵌套问题,条件变量用于线程间协作,读写锁优化读多写少场景,屏障则用于阶段性的线程汇合。在实际开发中,根据具体的需求场景选择合适的同步工具,是构建健壮、高效多线程程序的关键一步。

本文转载于:https://www.yisu.com/ask/42460512.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注