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

多线程 - 自旋锁

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

多线程 - 自旋锁

收录于专栏[Linux学习]
本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

概述

原理 

优点与缺点 

优点

缺点 

使用场景 

自旋锁伪代码实现

Linux 提供的自旋锁系统调用

注意事项

结论 

案例代码 


概述

自旋锁是一种多线程同步机制,用于保护共享资源免受并发访问的影响。在多个线程尝试获取锁时,它们会持续自旋(即在一个循环中不断检查锁是否可用)而不是立即进入休眠状态等待锁的释放。这种机制减少了线程切换的开销,适用于短时间内锁的竞争情况,但是不合理的使用,可能会造成 CPU 的浪费。 

原理 

自旋锁通常使用一个共享的标志位(如一个布尔值)来表示锁的状态。当标志位为 true 时,表示锁已被某个线程占用;当标志位为 false 时,表示锁可用。当一个线程尝试获取自旋锁时,它会不断检查标志位:

1. 如果标志位为 false,表示锁可用,线程将设置标志位为 true,表示自己占用了锁,并进入临界区。

2. 如果标志位为 true(即锁已被其他线程占用),线程会在一个循环中不断自旋等待,直到锁被释放。 

优点与缺点 

优点

1. 低延迟:自旋锁使用于短时间内的锁竞争情况,因为它不会让线程进入休眠状态,从而避免了线程转换的开销,提高了操作系统的效率。

2. 减少了系统调度开销: 当多个线程同时自旋等待同一个锁时,如果没有适当的退避策略,可能会导致所有线程都在不断检查锁状态而无法进入临界区,形成活锁。

缺点 

1. CPU 资源浪费:如果锁的持有时间较长,等待获取锁的线程会一直循环等待,导致 CPU 资源的浪费。

2. 可能引起活锁:当多个线程同时自旋等待同一个锁时,如果没有适当的退避策略,可能会导致所有线程都在不断地检查锁状态而无法进入临界区,形成活锁。 

使用场景 

1. 短暂等待地情况:使用于锁被占用时间很短地场景,如多线程对共享数据进行简单的读写操作。

2. 多线程的使用:通常用于系统底层,同步多个 CPU 对共享资源的访问。 

自旋锁伪代码实现

自旋锁的实现通常使用原子操作来保证操作的原子性,常用的软件实现方式是通过 CAS(Compare-And-Swap)指令实现。以下是一个简单的自旋锁实现示例(伪代码):

#include <stdio.h>
#include <stdatomic.h>
#include <pthread.h>
#include <unistd.h>
// 使用原子标志来模拟自旋锁
atomic_flag spinlock = ATOMIC_FLAG_INIT; // ATOMIC_FLAG_INIT 是0
// 尝试获取锁
void spinlock_lock()
{while (atomic_flag_test_and_set(&spinlock)){// 如果锁被占用,则忙等待}
}
// 释放锁
void spinlock_unlock()
{atomic_flag_clear(&spinlock);
}
typedef _Atomic struct
{
#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1_Bool __val;
#elseunsigned char __val;
#endif
} atomic_flag;

功能描述:

atomic_flag_test_and_set 函数检查 atomic_flag 的当前状态。如果 atomic_flag 之前没有被设置过(即其值为 false 或 未设置 状态),则函数会将其设置为 true(或 设置 状态),并返回先前的值(在这种情况下为 false)。如果 atomic_flag 之前已经被设置过(即其值为 true),则函数不会改变其状态,但会返回 true。


原子性:

这个操作是原子的,意味着在多线程环境中,它保证了对 atomic_flag 的读取和修改是不可分割的。当一个线程调用此函数时,其他线程无法看到这个操作的任何中间状态,这确保了操作的安全性。

Linux 提供的自旋锁系统调用

#include <pthread.h>
int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
int pthread_spin_unlock(pthread_spinlock_t *lock);
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
int pthread_spin_destroy(pthread_spinlock_t *lock);

注意事项

1. 在使用自旋锁时,需要确保锁被释放的时间尽可能短,以避免 CPU 资源的浪费。

2. 在多 CPU 环境下,自旋锁可能不如其他锁机制高效,因为它可能导致线程在不同的 CPU 上自旋等待。

结论 

自旋锁是一种适用于短时间内竞争情况的同步机制,它通过减少线程切换的开销来提高锁操作的效率。然而,它存在 CPU 资源浪费和可能引起活锁等缺点。在使用自旋锁时,需要根据具体的应用场景进行选择,并确保锁被释放的时间尽可能短。 

案例代码 

// 操作共享变量会有问题的售票系统代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>int ticket = 1000;
pthread_spinlock_t lock;void *route(void *arg)
{char *id = (char *)arg;while (1){pthread_spin_lock(&lock);if (ticket > 0){usleep(1000);printf("%s sells ticket:%d\n", id, ticket);ticket--;pthread_spin_unlock(&lock);}else{pthread_spin_unlock(&lock);break;}}return nullptr;
}int main(void)
{pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);pthread_t t1, t2, t3, t4;pthread_create(&t1, NULL, route, (void *)"thread 1");pthread_create(&t2, NULL, route, (void *)"thread 2");pthread_create(&t3, NULL, route, (void *)"thread 3");pthread_create(&t4, NULL, route, (void *)"thread 4");pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_join(t4, NULL);pthread_spin_destroy(&lock);return 0;
}

相关文章:

多线程 - 自旋锁

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 多线程 - 自旋锁 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 概述 原理 优点与…...

vue2 - Day02 -计算属性(computed)、侦听器(watch)和方法(methods)

在 Vue.js 中&#xff0c;计算属性&#xff08;computed&#xff09;、侦听器&#xff08;watch&#xff09;和方法&#xff08;methods&#xff09;都是响应式的数据处理方式 文章目录 1. 方法&#xff08;Methods&#xff09;1.1. 是什么1.2. 怎么用示例&#xff1a; 1.3. 特…...

Linux C 程序 【05】异步写文件

1.开发背景 Linux 系统提供了各种外设的控制方式&#xff0c;其中包括文件的读写&#xff0c;存储文件的介质可以是 SSD 固态硬盘或者是 EMMC 等。 其中常用的写文件方式是同步写操作&#xff0c;但是如果是写大文件会对 CPU 造成比较大的负荷&#xff0c;采用异步写的方式比较…...

Liveweb视频汇聚平台支持WebRTC协议赋能H.265视频流畅传输

随着科技的飞速发展和网络技术的不断革新&#xff0c;视频监控已经广泛应用于社会各个领域&#xff0c;成为现代安全管理的重要组成部分。在视频监控领域&#xff0c;视频编码技术的选择尤为重要&#xff0c;它不仅关系到视频的质量&#xff0c;还直接影响到视频的传输效率和兼…...

SQL组合查询

本文讲述如何利用 UNION 操作符将多条 SELECT 语句组合成一个结果集。 1. 组合查询 多数 SQL 查询只包含从一个或多个表中返回数据的单条 SELECT 语句。但是&#xff0c;SQL 也允许执行多个查询&#xff08;多条 SELECT 语句&#xff09;&#xff0c;并将结果作为一个查询结果…...

方正畅享全媒体新闻采编系统 screen.do SQL注入漏洞复现

0x01 产品简介 方正畅享全媒体新闻生产系统是以内容资产为核心的智能化融合媒体业务平台,融合了报、网、端、微、自媒体分发平台等全渠道内容。该平台由协调指挥调度、数据资源聚合、融合生产、全渠道发布、智能传播分析、融合考核等多个平台组成,贯穿新闻生产策、采、编、发…...

【机器学习】【集成学习——决策树、随机森林】从零起步:掌握决策树、随机森林与GBDT的机器学习之旅

这里写目录标题 一、引言机器学习中集成学习的重要性 二、决策树 (Decision Tree)2.1 基本概念2.2 组成元素2.3 工作原理分裂准则 2.4 决策树的构建过程2.5 决策树的优缺点&#xff08;1&#xff09;决策树的优点&#xff08;2&#xff09;决策树的缺点&#xff08;3&#xff0…...

Flink执行模式(批和流)如何选择

DataStream API支持不同的运行时执行模式(batch/streaming),你可以根据自己的需求选择对应模式。 DataStream API的默认执行模式就是streaming,用于需要连续增量处理并且预计会一直保持在线的无界(数据源输入是无限的)作业。 而batch执行模式则用于有界(输入有限)作业…...

LeetCode:101. 对称二叉树

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;101. 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输…...

LDO输入电压不满足最小压差时输出会怎样?

1、LDO最小压差 定义&#xff1a;低压差稳压器&#xff08;Low-dropout regulator&#xff0c;LDO&#xff09;LDO的最小压差Vdo指的是LDO正常工作时&#xff0c;LDO的输入电压必须高于LDO输出电压的差值&#xff0c;即Vin≥VdoVout   Vdo的值不是定值&#xff0c;会随着负载…...

源码分析之Openlayers中ZoomSlider滑块缩放控件

概述 ZoomSlider滑块缩放控件就是Zoom缩放控件的异形体&#xff0c;通过滑块的拖动或者点击滑槽&#xff0c;实现地图的缩放&#xff1b;另外其他方式控制地图缩放时&#xff0c;也会引起滑块在滑槽中的位置改变&#xff1b;即ZoomSlider滑块缩放控件会监听地图的缩放级别&…...

在Win11系统上安装Android Studio

诸神缄默不语-个人CSDN博文目录 下载地址&#xff1a;https://developer.android.google.cn/studio?hlzh-cn 官方安装教程&#xff1a;https://developer.android.google.cn/studio/install?hlzh-cn 点击Next&#xff0c;默认会同时安装Android Studio和Android虚拟机&#…...

华为ensp--BGP路径选择-AS_Path

学习新思想&#xff0c;争做新青年&#xff0c;今天学习的是BGP路径选择-AS_Path 实验目的: 理解AS_Path属性的概念 理解通过AS_Path属性进行选路的机制 掌握修改AS_Path属性的方法 实验内容: 本实验模拟了一个运营商网络场景&#xff0c;所有路由器都运行BGP协议&#xff…...

Android Java Ubuntu系统如何编译出 libopencv_java4.so

Cmake: cd ~ wget https://github.com/Kitware/CMake/releases/download/v3.30.3/cmake-3.30.3-linux-x86_64.tar.gztar -xzvf cmake-3.30.3-linux-x86_64.tar.gz sudo ln -sf $(pwd)/cmake-3.30.3-linux-x86_64/bin/* /usr/bin/cmake --versionAndroid NDK: wget https://…...

WPF Binding 绑定

绑定是 wpf 开发中的精髓&#xff0c;有绑定才有所谓的数据驱动。 1 . 背景 目前 wpf 界面可视化的控件&#xff0c;继承关系如下&#xff0c; 控件的数据绑定&#xff0c;基本上都要借助于 FrameworkElement 的 DataContext 属性。 只有先设置了控件的 DataContext 属性&…...

算法笔记—前缀和(动态规划)

【模板】前缀和_牛客题霸_牛客网 (nowcoder.com) #include <initializer_list> #include <iostream> #include <vector> using namespace std;int main() {//输入数据int n,q;cin>>n>>q;vector<int> arr;arr.resize(n1);for(int i1;i<…...

将HTML转换为PDF:使用Spire.Doc的详细指南(二)无水印版

目录 引言 一、准备工作 1. 下载Spire.Doc for Java破解版 2. 将JAR包安装到本地Maven (1) 打开命令提示符 (2) 输入安装命令 (3) 在pom.xml中导入依赖 二、实现HTML到PDF的转换 1. 创建Java类 2. 完整代码示例 3. 代码解析 4. 处理图像 5. 性能优化 6. 错误处理…...

V900新功能-电脑不在旁边,通过手机给PLC远程调试网关配置WIFI联网

您使用BDZL-V900时&#xff0c;是否遇到过以下这种问题&#xff1f; 去现场配置WIFI发现没带电脑&#xff0c;无法联网❌ 首次配置WIFI时需使用网线连电脑&#xff0c;不够快捷❌ 而博达智联为解决该类问题&#xff0c;专研了一款网关配网工具&#xff0c;实现用户现场使用手机…...

prober.php探针

raw.githubusercontent.com/kmvan/x-prober/master/dist/prober.php...

esp8266_TFTST7735语音识别UI界面虚拟小助手

文章目录 一 实现思路1 项目简介1.1 项目效果1.2 实现方式 2 项目构成2.1 软硬件环境2.2 完整流程总结&#xff08;重点整合&#xff09;(1) 功能逻辑图(2) 接线(3) 使用esp8266控制TFT屏(4)TFT_espI库配置方法(5) TFT_esp库常用代码详解(6)TFT屏显示图片(7) TFT屏显示汉字(8) …...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

JS红宝书笔记 - 3.3 变量

要定义变量&#xff0c;可以使用var操作符&#xff0c;后跟变量名 ES实现变量初始化&#xff0c;因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符&#xff0c;可以创建一个全局变量 如果需要定义…...

路由基础-路由表

本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中&#xff0c;往往存在多个不同的IP网段&#xff0c;数据在不同的IP网段之间交互是需要借助三层设备的&#xff0c;这些设备具备路由能力&#xff0c;能够实现数据的跨网段转发。 路由是数据通信网络中最基…...

中科院1区顶刊|IF14+:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点

中科院1区顶刊|IF14&#xff1a;多组学MR联合单细胞时空分析&#xff0c;锁定心血管代谢疾病的免疫治疗新靶点 当下&#xff0c;免疫与代谢性疾病的关联研究已成为生命科学领域的前沿热点。随着研究的深入&#xff0c;我们愈发清晰地认识到免疫系统与代谢系统之间存在着极为复…...

零基础在实践中学习网络安全-皮卡丘靶场(第十一期-目录遍历模块)

经过前面几期的内容我们学习了很多网络安全的知识&#xff0c;而这期内容就涉及到了前面的第六期-RCE模块&#xff0c;第七期-File inclusion模块&#xff0c;第八期-Unsafe Filedownload模块。 什么是"遍历"呢&#xff1a;对学过一些开发语言的朋友来说应该知道&…...