C++锁机制与信号机制对比分析

 更新时间:2025年06月21日 11:26:40   作者:张新颜  
文章介绍C++多线程编程中线程同步与通信的锁机制(互斥锁、读写锁及RAII封装)和信号机制(条件变量、信号量),并对比其在资源控制、并发限制和线程协调中的应用场景与优缺点,对C++锁机制与信号机制相关知识感兴趣的朋友一起看看吧

前言

在C++中,多线程编程的线程同步和通信主要依赖于锁机制和信号机制。

一、锁机制

锁用于控制对共享资源的访问,防止多个线程同时修改数据导致竞态条件。

  • 互斥锁(Mutex)
    作用:确保同一时间只有一个线程能访问共享资源。
    类型:
    ○ std::mutex:基本互斥锁。
    ○ std::recursive_mutex:允许同一线程多次加锁(解决递归调用中的锁问题)。
    ○ std::shared_mutex(C++17):读写锁,允许多个读线程或单个写线程访问。

基本用法

#include <mutex>
std::mutex mtx;
void thread_func() {
    mtx.lock();
    // 访问共享资源
    mtx.unlock();
}

RAII包装器(推荐使用,避免手动解锁):
std::lock_guard:自动在作用域内加锁和解锁。

{
    std::lock_guard<std::mutex> lock(mtx);
    // 自动加锁,离开作用域自动解锁
}

std::unique_lock:更灵活,支持延迟加锁和手动控制。

std::unique_lock<std::mutex> lock(mtx, std::defer_lock);
lock.lock(); // 手动加锁
// ...
lock.unlock(); // 可提前解锁
  • 读写锁(Shared Mutex)
    适用场景:读多写少的情况,提高并发性能。
    用法:
#include <shared_mutex>
std::shared_mutex rw_mtx;
// 读操作(共享锁)
{
    std::shared_lock<std::shared_mutex> lock(rw_mtx);
    // 多个读线程可同时访问
}
// 写操作(独占锁)
{
    std::unique_lock<std::shared_mutex> lock(rw_mtx);
    // 仅一个写线程可访问
}
  • 死锁预防
    原则:
    a. 按固定顺序加锁。
    b. 使用std::lock同时加多个锁(避免死锁)。
std::lock(mtx1, mtx2); // 原子性锁定多个互斥量
std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);
std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);

二、信号机制(条件变量)

  • 核心操作
  • 等待(Wait):线程在条件不满足时挂起。 通知(Notify):条件满足时唤醒等待的线程。
    notify_one():唤醒一个等待线程。
    notify_all():唤醒所有等待线程。
    基本用法等待条件(需配合互斥锁和谓词检查):
std::mutex mtx;
std::condition_variable cv;
bool data_ready = false;
// 等待线程
{
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return data_ready; }); // 防止虚假唤醒
    // 条件满足后执行操作
}
// 通知线程
{
    std::lock_guard<std::mutex> lock(mtx);
    data_ready = true;
    cv.notify_one(); // 或 notify_all()
}
  • 避免虚假唤醒
    使用带有谓词检查的wait:
cv.wait(lock, predicate); // 等价于 while (!predicate) cv.wait(lock);

三、信号量(Semaphore)

C++20 引入了std::counting_semaphore,用于控制同时访问资源的线程数量。

  • 基本用法
#include <semaphore>
std::counting_semaphore<10> sem(3); // 最大计数10,初始3
sem.acquire(); // 计数减1(如果计数为0则阻塞)
// 访问资源
sem.release(); // 计数加1
  • 适用场景
    ● 限制并发线程数(如连接池)。
    ● 生产者-消费者模型中的缓冲区控制。

四、锁与信号机制的对比

到此这篇关于C++锁机制与信号机制的文章就介绍到这了,更多相关C++锁机制与信号机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++读入

    C++读入"N,X,Y,Z"格式文本文件到Eigen3 Matrix

    这篇文章主要介绍了C++读入"N,X,Y,Z"格式文本文件到Eigen3 Matrix,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • C语言实现汉诺塔游戏

    C语言实现汉诺塔游戏

    个人觉得汉诺塔这个递归算法比电子老鼠的难了一些,不过一旦理解了也还是可以的,其实网上也有很多代码,可以直接参考。记得大一开始时就做过汉诺塔的习题,但是那时代码写得很长很长,也是不理解递归的结果。今天重新来实现一下
    2015-03-03
  • C语言版五子棋游戏的实现代码

    C语言版五子棋游戏的实现代码

    这篇文章主要为大家详细介绍了C语言版五子棋游戏的实现代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • C++实现LeetCode(203.移除链表元素)

    C++实现LeetCode(203.移除链表元素)

    这篇文章主要介绍了C++实现LeetCode(203.移除链表元素),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++11新特性之自定义字面量

    C++11新特性之自定义字面量

    这篇文章主要介绍了C++11新特性之自定义字面量的相关资料,帮助大家更好的学习c++,感兴趣的朋友可以了解下
    2020-08-08
  • C++STL之string类的使用

    C++STL之string类的使用

    这篇文章主要为大家详细介绍了C++STL中的string类,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • 详解C++11 原始字符串字面量(Json字符串表达更方便)

    详解C++11 原始字符串字面量(Json字符串表达更方便)

    原始字符串字面量(Raw String Literal)是C++11引入的一种字符串表示方式,用于简化字符串的定义,特别是当字符串中包含大量特殊字符(如换行符、双引号等)时,这篇文章给大家介绍C++11原始字符串字面量(Json字符串表达更方便)的相关知识,感兴趣的朋友一起看看吧
    2025-03-03
  • C++图文并茂分析讲解内存管理

    C++图文并茂分析讲解内存管理

    本章主要介绍C语言与C++的内存管理,以C++的内存分布作为引入,介绍C++不同于C语言的内存管理方式(new delete对比 malloc free),感兴趣的朋友来看看吧
    2022-09-09
  • 浅谈C++中virtual的三种用法

    浅谈C++中virtual的三种用法

    这篇文章主要介绍了浅谈C++中virtual的三种用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • C语言算法练习之折半查找的实现

    C语言算法练习之折半查找的实现

    二分查找法(也叫折半查找)其本质是分治算法的一种。这篇文章主要介绍了如何利用C语言实现折半查找,感兴趣的小伙伴可以学习一下
    2022-05-05

最新评论