四种锁(互斥锁,递归锁,读写锁,自旋锁)

2024-04-09 22:52

本文主要是介绍四种锁(互斥锁,递归锁,读写锁,自旋锁),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.互斥锁(mutex):互斥锁是最常见的一种锁,用来保护共享资源的互斥访问。一次只有一个线程可以获得互斥锁。如果其他线程试图获得已经被锁定的互斥锁,他们将被阻塞,直到锁被释放
2.递归锁(recursive lock):递归锁是一种特殊的互斥锁,允许同一个线程多次获得同一个锁,而不会导致死锁。递归锁维护了一个锁的计数器和一个拥有锁的线程标识
3.读写锁(read-write lock):读写锁允许多个线程同时读取共享资源,但再写入时需要互斥访问,这可以提高在读操作远多于写操作的场景下的性能
4.自旋锁(spinlock):自旋锁是一种特殊的锁,当锁已经被其他线程获得时,尝试获得锁的线程将忙等待(在一个循环中不断尝试获得锁),而不是被阻塞,自旋锁适用于锁持有时间非常短的场景

//递归锁

#include <iostream>
#include <thread>
#include <mutex>
struct Complex
{std::recursive_mutex mutex;int i;Complex() : i(0){}void mul(int x){std::lock_guard<std::recursive_mutex> lock(mutex);i *= x;}void div(int x){std::lock_guard<std::recursive_mutex> lock(mutex);i /= x;}void both(int x, int y){std::lock_guard<std::recursive_mutex> lock(mutex);mul(x);div(y);}
};
int main(void)
{Complex complex;complex.both(32, 23); //因为同一线程可以多次获取同一互斥量,不会发生死锁std::cout << "main finish\n";return 0;
}

互斥锁阻塞和唤醒的原理
1.当一个线程尝试获取互斥锁时,线程库会先查该锁是否已经被其他线程持有
2.如果锁没有被持有,线程库会将锁分配给线程,然后线程可以继续执行
3.如果锁已经被其他线程持有,线程会将请求线程挂起,挂起的线程会移除CPU的调度队列,进入等待队列,直到锁被释放。这样可以确保挂起的线程不会消耗CPU的资源
4.当持有锁的线程完成对共享资源的操作并释放锁之后,线程库会从等待队列中选择一个或多个挂起的线程,并将它们重新加入调度队列
5.被唤醒的进程会尝试重新获取锁,如果成功,线程会继续执行,否则,线程将再次被挂起,等待下一次通知

这篇关于四种锁(互斥锁,递归锁,读写锁,自旋锁)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/889429

相关文章

10. 文件的读写

10.1 文本文件 操作文件三大类: ofstream:写操作ifstream:读操作fstream:读写操作 打开方式解释ios::in为了读文件而打开文件ios::out为了写文件而打开文件,如果当前文件存在则清空当前文件在写入ios::app追加方式写文件ios::trunc如果文件存在先删除,在创建ios::ate打开文件之后令读写位置移至文件尾端ios::binary二进制方式

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api

java线程深度解析(二)——线程互斥技术与线程间通信

http://blog.csdn.net/daybreak1209/article/details/51307679      在java多线程——线程同步问题中,对于多线程下程序启动时出现的线程安全问题的背景和初步解决方案已经有了详细的介绍。本文将再度深入解析对线程代码块和方法的同步控制和多线程间通信的实例。 一、再现多线程下安全问题 先看开启两条线程,分别按序打印字符串的

PHP实现二叉树遍历(非递归方式,栈模拟实现)

二叉树定义是这样的:一棵非空的二叉树由根结点及左、右子树这三个基本部分组成,根据节点的访问位置不同有三种遍历方式: ① NLR:前序遍历(PreorderTraversal亦称(先序遍历)) ——访问结点的操作发生在遍历其左右子树之前。 ② LNR:中序遍历(InorderTraversal) ——访问结点的操作发生在遍历其左右子树之中(间)。 ③ LRN:后序遍历(PostorderT

oracle11.2g递归查询(树形结构查询)

转自: 一 二 简单语法介绍 一、树型表结构:节点ID 上级ID 节点名称二、公式: select 节点ID,节点名称,levelfrom 表connect by prior 节点ID=上级节点IDstart with 上级节点ID=节点值 oracle官网解说 开发人员:SQL 递归: 在 Oracle Database 11g 第 2 版中查询层次结构数据的快速

关于使用cspreadsheet读写EXCEL表格数据的问题

前几天项目有读写EXCEL表格的需求,我就找了大概有几种,大致分为:COM方法、ODBC方法、OLE方法、纯底层格式分析方法。由于COM方法要求必须安装有OFFICE的EXCEL组件,纯底层格式分析方法又很多功能需要自行去完善,所有最终选择了数据库的方法,用数据库的方法去存取xls格式的数据。网上有一个高手写的CSpreedSheet,看了一下提供的接口,感觉挺好用的。在使用的过程中发现几个

linux 内核提权总结(demo+exp分析) -- 任意读写(四)

hijack_modprobe_path篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm     原理同hijack_prctl, 当用户执行错误格式的elf文件时内核调用call_usermod

linux 内核提权总结(demo+exp分析) -- 任意读写(三)

hijack_prctl篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm   prctl函数: 用户态函数,可用于定制进程参数,非常适合和内核进行交互 用户态执行prctl函数后触发prctl系统

linux 内核提权总结(demo+exp分析) -- 任意读写(二)

hijack_vdso篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm     vdso: 内核实现的一个动态库,存在于内核,然后映射到用户态空间,可由用户态直接调用 内核中的vdso如果被修改