首页 游戏 软件 资讯 排行榜 专题
首页
编程语言
Linux C++程序如何实现并发控制

Linux C++程序如何实现并发控制

热心网友
32
转载
2026-05-03

在Linux环境下用C++搞并发,方法其实挺多的。选哪种,关键得看你的具体场景。下面咱们就聊聊几种常见的并发控制机制,并配上可以直接跑起来的代码示例。

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

Linux C++程序如何实现并发控制

1. 使用互斥锁(Mutex)

互斥锁,可以说是并发编程里的“老大哥”了。它的任务很明确:保护共享资源,确保同一时间只有一个线程能碰它。这能有效防止数据竞争,但用不好也容易导致死锁。

#include 
#include 
#include 

std::mutex mtx; // 全局互斥锁
int shared_data = 0;

void increment() {
    mtx.lock();   // 加锁
    ++shared_data;
    mtx.unlock(); // 解锁
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
    t1.join();
    t2.join();
    std::cout << "Shared data: " << shared_data << std::endl;
    return 0;
}

看这段代码,两个线程t1t2都想增加shared_data。没有锁的话,结果可能出乎意料;有了mtx这把锁,就能保证每次加法操作都是原子的。不过要提醒一点,手动调用lock()unlock()需要格外小心,万一在锁中间抛个异常或者忘了解锁,就麻烦了。所以更常见的做法是使用std::lock_guard

2. 使用递归互斥锁(Recursive Mutex)

普通互斥锁有个特点:同一个线程重复上锁会导致死锁。那如果函数会递归调用自己,或者需要多层加锁呢?这时候递归互斥锁就派上用场了。它允许同一个线程多次获得锁,只要解锁次数匹配就行。

#include 
#include 
#include 

std::recursive_mutex mtx; // 全局递归互斥锁
int shared_data = 0;

void increment(int count) {
    if (count <= 0) return;
    mtx.lock();   // 加锁
    ++shared_data;
    std::cout << "Thread " << std::this_thread::get_id() << " incremented shared_data to " << shared_data << std::endl;
    mtx.unlock(); // 解锁
    increment(count - 1); // 递归调用
}

int main() {
    std::thread t1(increment, 5);
    std::thread t2(increment, 3);
    t1.join();
    t2.join();
    std::cout << "Final shared data: " << shared_data << std::endl;
    return 0;
}

这个例子里,increment函数会递归调用自己。如果用普通mutex,线程第一次进入函数锁上后,在递归调用时试图再次获取锁,就会把自己永远挂起。换成recursive_mutex就顺畅了。当然,递归锁通常比普通锁开销大一点,非必要不使用。

3. 使用条件变量(Condition Variable)

条件变量解决的是另一类问题:线程间的协同等待。比如,一个线程需要等待某个条件成立(比如数据准备好了)才能继续,而另一个线程负责在条件满足时通知它。这是实现生产者-消费者模型的核心工具之一。

#include 
#include 
#include 
#include 

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

void worker() {
    std::unique_lock lock(mtx);
    cv.wait(lock, []{ return ready; }); // 等待条件成立
    std::cout << "Worker thread is processing data..." << std::endl;
}

void trigger() {
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟一些准备工作
    {
        std::lock_guard lock(mtx);
        ready = true;
    }
    cv.notify_one(); // 通知一个等待的线程
}

int main() {
    std::thread t1(worker);
    std::thread t2(worker);
    trigger();
    t1.join();
    t2.join();
    return 0;
}

注意看cv.wait的用法,它接受一个锁和一个谓词(lambda表达式)。这样写可以防止“虚假唤醒”——即条件变量可能因为系统原因而返回,但条件并未真正满足。使用谓词判断,就能确保唤醒时条件一定为真。另外,通知线程在修改条件变量关联的布尔标志ready时,也必须在锁的保护下进行,这是标准做法。

4. 使用原子操作(Atomic Operations)

如果共享的操作非常简单,比如只是对一个整数进行加减,那么上锁就显得有点“杀鸡用牛刀”了,性能开销不小。这时候,原子类型就是更好的选择。它在底层通过CPU指令保证操作的不可分割性,既安全又高效。

#include 
#include 
#include 

std::atomic shared_data(0);

void increment() {
    ++shared_data; // 这是一个原子操作
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
    t1.join();
    t2.join();
    std::cout << "Shared data: " << shared_data << std::endl;
    return 0;
}

代码简洁多了,不是吗?std::atomic保证了++shared_data这个操作是原子的,无需额外锁。原子操作非常适合计数器、状态标志等简单场景。但要注意,它只能保证单个操作的原子性;如果需要保护多个相关联变量的修改,或者一个复杂的临界区,还是得靠互斥锁。

5. 使用读写锁(Read-Write Lock)

最后来看一种更精细的锁策略:读写锁。它基于一个很常见的观察——读操作往往远多于写操作,而且读操作之间通常不会冲突。读写锁(C++17中的std::shared_mutex)允许多个线程同时读,但写操作是独占的。这能在读多写少的场景下大幅提升并发性能。

#include 
#include 
#include 

std::shared_mutex rw_mtx; // 全局读写锁
int shared_data = 0;

void reader() {
    std::shared_lock lock(rw_mtx); // 上读锁
    std::cout << "Reader thread read shared_data: " << shared_data << std::endl;
}

void writer() {
    std::unique_lock lock(rw_mtx); // 上写锁
    ++shared_data;
    std::cout << "Writer thread wrote shared_data: " << shared_data << std::endl;
}

int main() {
    std::thread t1(reader);
    std::thread t2(writer);
    std::thread t3(reader);
    t1.join();
    t2.join();
    t3.join();
    return 0;
}

这里的关键在于锁的类型:读线程使用std::shared_lock,这意味着多个读锁可以共存;写线程使用std::unique_lock,它和普通的互斥锁一样是独占的。当有写锁存在时,所有读锁和写锁请求都必须等待。这种机制完美适配了配置读取、缓存访问等场景。

好了,以上就是Linux C++并发编程中几种核心的同步机制。从最基础的互斥锁,到应对特殊场景的递归锁,再到用于线程协作的条件变量,以及追求性能极致的原子操作和读写锁,每种工具都有其用武之地。实际开发中,往往需要根据数据访问模式、性能要求和代码复杂度来灵活选择和组合。理解它们的特性和代价,是写出稳健高效并发程序的第一步。

来源:https://www.yisu.com/ask/30673985.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

Filebeat如何实现跨平台日志收集
编程语言
Filebeat如何实现跨平台日志收集

Filebeat跨平台日志收集实践指南 一 架构与关键点 面对混合IT环境,如何用一套工具搞定所有主机的日志收集?Filebeat给出了答案。它提供了覆盖Linux、Windows和macOS的安装包,这意味着,你只需要维护同一套简洁的YAML配置,就能在不同操作系统上实现统一的日志采集与输出。其轻

热心网友
05.03
Filebeat如何进行日志压缩与归档
编程语言
Filebeat如何进行日志压缩与归档

Filebeat日志压缩与归档实践 说到日志管理,很多朋友会问:Filebeat本身能搞定日志的本地压缩和长期归档吗?答案是,这事儿得分两头看。Filebeat的核心任务是采集和转发,它并不包办所有存储和归档的活儿。一个典型的实践方案是:本地用系统工具处理Filebeat自己的日志,防止磁盘爆满;远

热心网友
05.03
如何利用Filebeat进行故障排查
编程语言
如何利用Filebeat进行故障排查

Filebeat故障排查实操手册 日志采集管道卡住了?数据流突然中断?别慌,这往往是Filebeat在“报警”。作为数据管道的第一公里,它的稳定至关重要。下面这份实操指南,能帮你像老手一样,快速定位并解决大多数常见问题。 一、快速定位流程 遇到问题,按这个顺序走一遍,十有八九能找到症结所在。 确认服

热心网友
05.03
如何自定义Filebeat日志格式
编程语言
如何自定义Filebeat日志格式

Filebeat日志格式自定义指南 一 概念澄清 在动手配置之前,先得把两个容易混淆的概念理清楚: Filebeat自身运行日志:这指的是Filebeat这个“搬运工”自己工作时产生的日志,比如它有没有正常启动、遇到了什么错误。这类日志通常输出到磁盘文件或控制台,方便运维人员排错。你可以选择让它以纯

热心网友
05.03
HDFS快照如何使用
编程语言
HDFS快照如何使用

HDFS 快照使用指南 说到数据备份与恢复,HDFS快照绝对是一个高效且轻量的利器。它本质上就是文件系统在某个特定时刻的“只读照片”,专门用于应对误操作或进行历史状态对比。那么,它到底是怎么工作的?简单来说,有以下几个核心特性: 一 核心概念与适用场景 首先,HDFS快照的创建几乎是瞬间完成的,时间

热心网友
05.03

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

爱玛电动车开座位要钥匙吗?
电脑教程
爱玛电动车开座位要钥匙吗?

爱玛电动车座垫开启指南:无钥匙方案与应急操作全解析 想要打开爱玛电动车的座垫,其实多数情况下并不需要钥匙。具体操作方法取决于您的车型配置与锁具设计。不同型号的电动车,其座垫开启方式存在显著差异。部分中高端车型已搭载电子按键或感应式座垫锁,只需轻按车把周边、仪表盘侧方或座垫边缘的实体按钮,座垫即可自动

热心网友
05.03
小米MIX4升级澎湃2.0需要解锁Bootloader吗?
电脑教程
小米MIX4升级澎湃2.0需要解锁Bootloader吗?

小米MIX4升级澎湃OS 2 0指南:官方OTA直达,无需解锁Bootloader 对于小米MIX4用户而言,升级至全新的澎湃OS 2 0系统,过程异常简便。小米官方已将该机型纳入首批正式版全量推送计划,用户无需进行复杂的Bootloader解锁操作,即可通过无线升级(OTA)方式平滑过渡。整个升级

热心网友
05.03
爱玛电动车怎么开座位?
电脑教程
爱玛电动车怎么开座位?

爱玛电动车车座开启全攻略:三种可靠方式详解 想要打开爱玛电动车的坐垫,其实方法多样且设计周全。厂家为用户提供了三种经过国家标准认证的可靠开启方案:经典的机械钥匙旋转、便捷的遥控器一键操作,以及面向未来的智能终端控制。绝大多数车型都在坐垫左后方区域配备了独立的物理钥匙孔,确保了基础开启的可靠性。中高端

热心网友
05.03
买eth的美股上市公司有哪些?为什么选择押注 ETH 而非 BTC
web3.0
买eth的美股上市公司有哪些?为什么选择押注 ETH 而非 BTC

自2025年起,SharpLink Gaming、Bitmine Immersion Tech、Bit Digital 与 BTCS Inc 四家美股公司通过大规模购入并质押 ETH,开创了“ETH 微策略”。 自2025年以来,美股市场出现了一股引人注目的新潮流。以SharpLink Gamin

热心网友
05.03
路由器怎么安装和设置连wifi上网显示无网络?
电脑教程
路由器怎么安装和设置连wifi上网显示无网络?

路由器安装与设置的核心:三步闭环搞定网络连接 路由器安装后,Wi-Fi信号满格却显示“无网络访问”,这种情况确实令人困扰。但请先别急于断定设备损坏,绝大多数问题并非硬件故障,而是网络连接的“链路”在某个配置环节出现了中断。整个排查过程的核心,可以总结为“物理连通、参数匹配、逻辑生效”三步闭环法则。只

热心网友
05.03