锁的基本介绍

并发编程的一个最基本问题就是原子性地执行一系列指令。锁有助于直接解决这一问题。

锁的基本思想

锁就是一个变量。这个变量保存了锁在某一时刻的状态。它要么是可用的,表示没有线程持有锁,要么是被占用的,表示有线程持有锁,正处于临界区(访问共享资源的那部分代码)。

Pthread锁

POSIX库将锁称为互斥量(mutex),因为它被用来提供线程之间的互斥。当一个线程在临界区,它能阻止其它线程进入到本地线程直到本线程离开临界区。

设计锁

一个锁应当能保证不会有第二个线程进入临界区。另外,还应当保证公平性,所有的线程都有机会公平抢到锁。在设计锁时还应该考虑到抢锁和释放锁的开销。

为了实现上面两点,我们需要使用硬件和操作系统的支持。

控制中断

在临界区关闭中断。这个方案是为单处理系统开发的。

原子交换(测试并设置)

控制中断无在多处理器上工作,系统设计者开始让硬件支持锁。最简单的硬件支持就是测试并设置指令(test-and-set instruction),也叫做原子交换。

typedef struct lock_t { int flag; } lock_t;void init(lock_t* mutex)
{mutex->flag = 0;
}void lock(lock_t* mutex)
{while (mutex->flag == 1) //测试; //锁被其它线程占用,该线程陷入自旋mutex->flag = 1; //设置
}void unlock(lock_t* mutex)
{mutex->flag = 0;
}

这种设置也是有问题的,首先它不能完成让线程互斥的基本任务。考虑这种情况,当线程1在测试锁时(只是通过了测试并未设置),发生了中断切换的线程2,随后线程2执行了完整的测试和设置,此时再次发生中断切换到线程1。由于先前线程1已经通过了测试语句,接下来会执行设置代码。这样一来,就有两个线程同时持有锁了。

在性能上,如果一个线程在等待已经被持有的锁时,会一直自旋,不停地检查锁。这会浪费许多CPU时间。

实现这种锁,需要一条硬件指令支持。在x86上是xchg指令(原子交换)。下面的代码片段说明了该指令的工作方式:

int TestAndSet(int* old_ptr, int new)
{int old = *old_ptr;*old_ptr = new;return old;
}

这些代码都是原子地执行。利用这类原子交换指令可以实现自旋锁。

typedef struct lock_t
{int flag;
} lock_t;void init(lock_t* lock)
{lock->flag = 0;
}void lock(lock_t* lock)
{while (TestAndSet(lock, 1) == 1);//自旋
}void unlock(lock_t* lock)
{lock->flag = 0;
}

比较并交换

另一个硬件支持是比较并交换指令。

int CompareAndSwap(int *ptr, int expected, int new)
{int actual = *ptr;if (actual == expected)*ptr = new;return actual;
}

链接的加载和条件式存储指令

int LoadLinked(int* ptr)
{return *ptr;
}int StoreConditional(int* ptr, int value)
{if (no one has updated *ptr since the LoadLinked to this address){*ptr = value;return 1;}else{return 0;}
}

获取并增加

int FetchAndAdd(int *ptr)
{int old = *ptr;*ptr = old + 1;return old;
}typedef struct lock_t
{int ticket;int turn;
} lock_t;void lock_init(lock_t *lock)
{lock->ticket = 0;lock->turn = 0;
}void lock(lock_t* lock)
{int myturn = FetchAndAdd(&lock->ticket);while (lock->turn != myturn); //spin
}void unlock(lock_t* lock)
{FetchAndAdd(&lock->turn);
}

解决自旋时的浪费

在自旋的时候,线程应该放弃CPU,从运行状态变为就绪状态。而且我们应该控制释放锁时谁可以抢到锁,这是为了避免性能上的浪费以及饿死的问题。

为此,我们需要操作系统维护一个队列保存正在等待锁的线程队列。这样我们就可以在锁被占用时休眠线程,在锁可用时从队头中唤醒一个线程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/918709.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/918709.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【读代码】开源流式语音编码器SecoustiCodec

引言:从LLM到深度语义 在大型语言模型(LLM)驱动的语音交互时代,神经语音编解码器 (Neural Speech Codec) 扮演着至关重要的角色。它如同 LLM 的“耳朵”和“嘴巴”,负责将连续的语音波形转换为离散的、可供模型处理的 token,并将模型生成的 token 还原为自然的人声。 一…

P5967 [POI 2016] Korale 题解

P5967 [POI 2016] Korale 题目描述 有 nnn 个带标号的珠子,第 iii 个珠子的价值为 aia_iai​。 现在你可以选择若干个珠子组成项链(也可以一个都不选),项链的价值为所有珠子的价值和。 给出所有可能的项链排序,先按…

SwiftUI 页面弹窗操作

SwiftUI 页面弹窗操作指南一、基础弹窗实现1. Alert 基础警告框2. ActionSheet 操作菜单3. Sheet 模态视图4. Popover 浮动视图二、高级自定义弹窗1. 自定义弹窗组件2. 使用自定义弹窗三、弹窗状态管理1. 使用环境对象管理弹窗2. 弹窗路由系统四、动画与过渡效果1. 自定义弹窗动…

OpenCV图像处理2:边界填充与平滑滤波实战

前面学了一些关于opencv图像处理的内容,现在继续。一 图像填充边界填充(Border Padding)​,即在图像四周添加指定宽度的像素区域。其核心函数是cv2.copyMakeBorder(),通过不同的填充方式(borderType&#x…

imx6ull-驱动开发篇22——Linux 时间管理和内核定时器

目录 内核时间管理 系统节拍率 高/低节拍率的优缺点 jiffies 节拍数 时间绕回 时间转换函数 内核定时器 timer_list 结构体 定时器API函数 init_timer 函数 add_timer 函数 del_timer 函数 del_timer_sync 函数 mod_timer 函数 Linux 内核短延时函数 内核时间管…

路由器数据控制管理层面安全

数据层面:FPM Flexible Packet MatchingFPM是CisCOIOS新一代的ACL根据任意条件,无无状态的匹配数据包的头部负载,或者全部分析协议,更易于规则的创建用于替代传统ACL,对特定恶意流量的基础架构过滤无状态ipv4单播不支持…

Vue内置组件全解析:从入门到面试通关

文章目录Vue内置组件全解析&#xff1a;从入门到面试通关引言&#xff1a;为什么需要内置组件&#xff1f;一、Vue内置组件全景图二、核心内置组件详解1. <component> - 动态组件2. <transition> - 过渡动画3. <keep-alive> - 组件缓存4. <slot> - 内容…

VUE+SPRINGBOOT从0-1打造前后端-前后台系统-会议记录

在当今快节奏的工作环境中&#xff0c;会议记录是每个职场人士都必须要面对的任务。传统的手动记录方式不仅效率低下&#xff0c;而且容易遗漏重要信息。随着Web技术的发展&#xff0c;基于浏览器的实时语音转写技术为会议记录提供了全新的解决方案。本文将详细介绍如何利用Web…

WEB3——水龙头,如何获得开发用的测试币、 Sepolia 测试币?

注意&#xff1a; 有些水龙头渠道&#xff0c;要求以太坊币至少有0.01ETH,设有这个门槛&#xff0c;下面并不是所有渠道都能领取到测试币&#xff0c;有些可能对领取测试币有要求&#xff0c;如果想获得获取以太坊币的方法&#xff0c;可以看我其他的文章。 本文整理了多个免费…

C++调试革命:时间旅行调试实战指南

还在为C的悬垂指针、内存泄漏和并发竞态抓狂&#xff1f;让调试器学会“时光倒流” 凌晨三点&#xff0c;std::thread创建的六个线程中有一个突然吞掉了你的数据&#xff0c;valgrind只告诉你“Invalid read”&#xff0c;而时间旅行调试&#xff08;TTD&#xff09;​​ 能让你…

mysql8.0笔记

1.DDL数据定义语言 DDL是什么——————创建、修改、删除 数据库和表结构的命令。 基本语法 针对数据库的操作 -- 创建数据库 CREATE DATABASE 数据库名; -- 比如 CREATE DATABASE myschool; --查看所有数据库 SHOW DATABASES; --使用某个数据库 USE myschool; -- 删除数据库…

大模型微调【1】之入门

文章目录说明一 大模型微调技术1.1 微调基础1.2 量化概念1.3 高效微调方法LoRA&QLoRA1.4 LoRA VS QLoRA1.5 高效微调的应用场景二 主流微调工具2.1 unsloth2.2 LLama-Factory2.3 ms-SWIFT2.4 ColossalAI2.5 底层微调框架推荐2.6 模型性能评估框架EvalScope三 微调所需软硬件…

深入解析Linux poll()系统调用

&#x1f504; Linux poll() 系统调用详解一、poll 是干什么的&#xff1f;poll 是 Linux&#xff08;及 POSIX 标准&#xff09;中用于实现 I/O 多路复用&#xff08;I/O Multiplexing&#xff09; 的系统调用&#xff0c;它的核心作用是&#xff1a;让一个线程能够同时监视多…

文献阅读 | PLoS ONE | SRplot:一个免费的在线平台,用于数据可视化和图形

文献介绍文献题目&#xff1a; SRplot&#xff1a;一个免费的在线平台&#xff0c;用于数据可视化和图形 研究团队&#xff1a; Yewei Wang&#xff08;中南大学湘雅二医院&#xff09; 发表时间&#xff1a; 2023-11-09 发表期刊&#xff1a; PLoS ONE 影响因子&#xff1a; 3…

分布式与微服务宝典

分布式理论基础 1、分布式架构有哪些特点&#xff0c;优势和缺陷 特点&#xff1a;微服务架构的优点微服务架构的缺陷自由使用不同技术增加故障排除挑战每一个微服务都侧重于单一功能由于远程调用增加延迟支持单个可部署单元增加了配置与其他操作的工作量允许经常发布软件难以保…

利用生成式AI与大语言模型(LLM)革新自动化软件测试 —— 测试工程师必读深度解析

引言 自动化测试是现代软件工程的基石&#xff0c;然而&#xff0c;随着软件复杂度和迭代速度的飞速提升&#xff0c;传统自动化测试方法正面临越来越多的挑战。 近年来&#xff0c;生成式人工智能&#xff08;Generative AI&#xff09;和大语言模型&#xff08;LLM&#xff0…

JS 与 C++ 双向通信实战:基于 WebHostViewListener 的消息处理机制

前言在现代浏览器和桌面应用开发中&#xff0c;WebView 嵌入已经成为一种非常常见的 UI 技术方案。无论是基于 Chromium 的 CEF&#xff08;Chromium Embedded Framework&#xff09;、Qt WebEngine&#xff0c;还是自研浏览器内核&#xff0c;嵌入 WebView 都能带来极高的灵活…

模板打印技术——Office XLS 打印模板:为政务土地确权定制的纸张替换利器—仙盟创梦IDE

代码public static int cyberwin_replaceExcelandoutputPrint(string fisrcpathleurl, DataTable dtInfo, string despath){if (File.Exists(despath) true){//删除目标文件File.Delete(despath);}File.Copy(fisrcpathleurl, despath);string 目标文件 despath;MSEXCEL.Appli…

可直接运行的 Playwright C# 自动化模板

目录 目录结构 1. appsettings.json&#xff08;账号、URL、路径配置&#xff09; 2. Program.cs&#xff08;启动入口&#xff09; 3. SchedulerConfig.cs&#xff08;定时调度&#xff09; 4. SocialSecurityTask.cs&#xff08;自动报社保任务&#xff09; 5. QuerySo…

云平台监控-云原生环境Prometheus企业级监控实战

目录 一、基于 Kubernetes 的 Prometheus 监控方案概述 1. 核心组件及功能 2. 监控流程详解 3. 关键监控指标说明 二、Prometheus 与相关组件部署 1. 克隆项目代码 2. 安装 Prometheus Operator 3. 安装 Prometheus Stack 4. 查看容器运行状态 三、ServiceMonitor 配…