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语言 数组指针详解及示例代码

    本文主要介绍C语言 数组指针,这里整理了相关资料并附示例待会及实现结果,帮助大家学习C语言中指针的知识,有需要学习此部分内容的朋友可以参考下
    2016-08-08
  • C++避免栈内存溢出的几种实现方法

    C++避免栈内存溢出的几种实现方法

    在C++编程中,一个线程的栈内存通常是有限的,本文就来详细介绍几种避免栈溢出的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09
  • 使用C语言顺序表数据结构实现栈的代码示例

    使用C语言顺序表数据结构实现栈的代码示例

    这篇文章主要给大家介绍了如何使用C语言顺序表数据结构实现栈,文章通过代码示例介绍的非常详细,对大家的学习或工作有一定的参考价值,需要的朋友可以参考下
    2023-09-09
  • 介绍C语言中tolower函数的实例

    介绍C语言中tolower函数的实例

    这篇文章主要介绍了介绍C语言中tolower函数的实例,本文列出了该函数的头文件,功能说明等,以及如何使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++超详细讲解函数重载

    C++超详细讲解函数重载

    C++ 允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载(Function Overloading),借助重载,一个函数名可以有多种用途
    2022-05-05
  • C语言实现学籍管理系统课程设计

    C语言实现学籍管理系统课程设计

    这篇文章主要为大家详细介绍了C语言实现学籍管理系统课程设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • 用C语言实现五子棋游戏

    用C语言实现五子棋游戏

    这篇文章主要为大家详细介绍了用C语言实现五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • C++ explicit关键字的使用详解

    C++ explicit关键字的使用详解

    这篇文章主要介绍了C++ explicit关键字的使用详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • 利用C++实现最长公共子序列与最长公共子串

    利用C++实现最长公共子序列与最长公共子串

    这篇文章主要给大家介绍了如何利用C++实现最长公共子序列与最长公共子串,文章一开始就给大家简单的介绍了什么是子序列,子串应该比较好理解就不用多介绍了,人后通过算法及示例代码详细介绍了C++实现的方法,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-12-12
  • 谈谈C++学习之Pair的使用方法

    谈谈C++学习之Pair的使用方法

    pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同,本篇详细的介绍了Pair的使用方法和实例,有兴趣的同学可以了解一下。
    2016-12-12

最新评论