当前位置: 首页 > news >正文

【C++】详解std::mutex

2023年9月11日,周一中午开始

2023年9月11日,周一晚上23:25写完


目录

  • 概述
  • 头文件
  • std::mutex类的成员
  • 类型
  • 方法
  • 没有std::mutex会产生什么问题
  • 问题一:数据竞争
  • 问题二:不一致
  • lock和unlock
  • 死锁

概述

std::mutex是C++标准库中提供的一种同步原语,用于保护共享资源的访问

std::mutex通过锁定互斥锁来实现对共享资源的保护。当一个线程获取了互斥锁后,其他线程必须等待该互斥锁被释放才能继续访问共享资源。这样可以确保在同一时刻只有一个线程能够访问共享资源,从而避免了多个线程同时访问同一资源而导致的数据竞争不一致问题。

头文件

#include<mutex>

std::mutex类的成员

类型

native_handle_type    原生的互斥锁句柄类型

方法

(constructor)    构造互斥锁(公共函数)

lock    锁上互斥锁(公共函数)

try_lock    如果互斥锁没锁上就锁上互斥锁(公共函数)

unlock    解除互斥锁(公共函数)

native_handle    获取原生的互斥锁句柄(公共函数)

没有std::mutex会产生什么问题

问题一:数据竞争

在这个程序中,共享资源是count,count的值为0

按理来说,一个线程给count增加100000,另一个线程给count减去100000,最后的count应该还是0,但是事实上却不是这样,这就是数据竞争所造成的。

#include <iostream>
#include <mutex>
#include <thread>int count = 0;void thread1() {for(int i = 0; i < 100000; i++) {count++; }
}void thread2() {for(int i = 0; i < 100000; i++) {  count--;}
}int main() {std::thread t1(thread1);std::thread t2(thread2);t1.join();t2.join();std::cout <<"count:"<< count << std::endl; // 可能打印非0值
}

问题二:不一致

多个线程对共享数据进行操作,由于缓存一致性问题,可能导致其中一个线程看到的数据不是最新值。

比如在这个程序里面,有时候判断x==1是true,有时候判断x==1是false

#include <iostream>
#include <mutex>
#include <thread>int x = 0;void thread1() {x = 1; 
}void thread2() {if(x == 1)std::cout << "x is 1" << std::endl; elsestd::cout << "x is not 1" << std::endl; 
}int main() {std::thread t1(thread1);std::thread t2(thread2);t1.join();t2.join();}

lock和unlock

通过lock/unlock可以保证任何时刻只有一个线程在访问共享资源,从而避免数据竞争问题。

#include <iostream>
#include <mutex>
#include <thread>std::mutex mutex;
int count = 0;void thread1() {for(int i = 0; i < 100000; i++) {// 锁定互斥锁mutex.lock();  count++; // 解锁互斥锁mutex.unlock();}
}void thread2() {for(int i = 0; i < 100000; i++) {  // 锁定互斥锁mutex.lock();  count--;// 解锁互斥锁mutex.unlock();}
}int main() {std::thread t1(thread1);std::thread t2(thread2);t1.join();t2.join();std::cout <<"count:"<< count << std::endl; 
}

可以看到数据竞争的问题得到了解决

死锁

死锁(Deadlock)是多线程或多进程编程中的一个严重问题,它会导致程序无法继续执行下去,因为一组线程或进程相互等待对方释放资源,但永远无法满足条件,从而陷入僵局。

死锁的定义是:多个线程因为抢占和持有资源而造成的一种互相等待的僵局状态

#include <iostream>
#include <thread>
#include <mutex>std::mutex mutex1;
std::mutex mutex2;void threadA() {std::cout << "Thread A: Attempting to lock mutex1..." << std::endl;mutex1.lock();std::this_thread::sleep_for(std::chrono::milliseconds(1));std::cout << "Thread A: Attempting to lock mutex2..." << std::endl;mutex2.lock();// 执行任务...mutex2.unlock();mutex1.unlock();
}void threadB() {std::cout << "Thread B: Attempting to lock mutex2..." << std::endl;mutex2.lock();std::this_thread::sleep_for(std::chrono::milliseconds(1));std::cout << "Thread B: Attempting to lock mutex1..." << std::endl;mutex1.lock();// 执行任务...mutex1.unlock();mutex2.unlock();
}int main() {std::thread t1(threadA);std::thread t2(threadB);t1.join();t2.join();return 0;
}

可以看到程序一直卡住

为什么会卡住呢?

  1. 线程A首先尝试锁定mutex1,并成功获得锁。

  2. 线程B首先尝试锁定mutex2,并成功获得锁。

  3. 接下来,线程A想要锁定mutex2,但它被线程B持有,因此线程A被阻塞,无法继续执行,等待mutex2被释放。

  4. 同样地,线程B想要锁定mutex1,但它被线程A持有,因此线程B也被阻塞,等待mutex1被释放。

现在,线程A和线程B都被阻塞,它们相互等待对方释放资源,但又不会主动释放自己的锁。这就是典型的死锁情况:两个或多个线程互相等待对方释放资源,导致程序无法继续执行下去。

根本原因在于线程拿不到锁时就会被阻塞。

http://www.lryc.cn/news/169776.html

相关文章:

  • Matlab图像处理-Lab模型
  • 分布式ETL工具Sqoop实践
  • 展会预告 | 图扑邀您共聚 IOTE 国际物联网展·深圳站
  • 如何下载安装 WampServer 并结合 cpolar 内网穿透,轻松实现对本地服务的公网访问
  • iOS添加Mapbox地图库
  • destoon根据目录下的html文件生成地图索引
  • gRPC之gRPC流
  • Kafka Shell命令交互
  • 什么是回归测试?
  • ZTMap是如何在相关政策引导下让建筑更加智慧化的?
  • Python:函数和代码复用
  • three.js——模型对象的使用材质和方法
  • sql explain
  • 【LeetCode-简单题】剑指 Offer 05. 替换空格
  • 数字虚拟人制作简明指南
  • Nginx 文件解析漏洞复现
  • Lombok依赖
  • XML 和 JSON 学习笔记(基础)
  • L1-005 考试座位号分数 15
  • 无涯教程-JavaScript - CEILING.MATH函数
  • ChatGPT提示词(prompt)资源汇总
  • MySQL 几种导数据的方法与遇到的问题
  • (21)多线程实例应用:双色球(6红+1蓝)
  • 升级OpenSSL并进行编译安装
  • Spring整合RabbitMQ
  • MySQL——事务和视图
  • 做好制造项目管理的5个技巧
  • JavaScript中While循环
  • python经典百题之乒乓球比赛
  • 【C++ Exceptions】Catch exceptions by reference!