IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++读写锁造成死锁 -> 正文阅读

[C++知识库]C++读写锁造成死锁

C++14支持std::shared_timed_mutex

C++17支持std::shared_mutex

前者相比后者支持的操作更多,但是后者相对性能更好。

  • 使用std::lock_guard<std::shared_mutex>std::unique_lock<std::shared_mutex>互斥访问
  • 使用std::shared_lock<std::shared_mutex>实现共享访问(C++14),使用方式和std::unique_lock相同

多个线程可以同时共享访问std::shared_mutex,但是如果在读锁上获取写锁,会使得写锁阻塞,直到所有读锁释放,同时写锁也会阻塞后面的读锁防止写锁饥饿。

假如一个线程A的函数需要读锁1,其内部运行的某个函数也需要读锁2,在线程A得到读锁1后另一个线程B需要写锁,线程B写锁上锁以后会阻塞等待线程A释放读锁1,线程A继续向下运行,等到第二次拿读锁2的时候,为了避免不断读锁上锁造成对写锁的饥饿,读锁2会阻塞等待线程B写锁释放,因此造成了死锁。

我自己写了一个小的Demo,的确会造成死锁。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <shared_mutex>

using namespace std;

void print() {
    cout << "\n";
}
template<typename T, typename... Args>
void print(T&& first, Args&& ...args) {
    cout << first << " ";
    print(std::forward<Args>(args)...);
}

std::shared_mutex mtx;
int step = 0;
std::mutex cond_mtx;
std::condition_variable cond;

void read() {
    //step0: 读锁
    shared_lock<std::shared_mutex> lock(mtx);
    
    unique_lock<std::mutex> uniqueLock(cond_mtx);
    print("read lock 1");
    //通知step0结束
    ++step;
    cond.notify_all();
    //等待step1: 写锁 结束
    cond.wait(uniqueLock, []{
        return step == 2;
    });
    uniqueLock.unlock();
    
    //step2: 再次读锁
    shared_lock<std::shared_mutex> lock1(mtx);
    
    print("read lock 2");
}

void write() {
    //等待step0: 读锁 结束
    unique_lock<std::mutex> uniqueLock(cond_mtx);
    cond.wait(uniqueLock, []{
        return step == 1;
    });
    uniqueLock.unlock();
    
    //step1: 写锁
    lock_guard<std::shared_mutex> lock(mtx);
    
    uniqueLock.lock();
    print("write lock");
    //通知step1结束
    ++step;
    cond.notify_all();
    uniqueLock.unlock();
    
}

int main() {
    std::thread t_read{read};
    std::thread t_write{write};
    t_read.join();
    t_write.join();
    return 0;
}

为了避免死锁,应该像陈硕大神建议的那样使用智能指针+互斥锁实现copy on write来代替读写锁。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-13 11:37:20  更:2022-05-13 11:38:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 18:32:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码