C++实战篇(一)——自旋锁的使用

参考文章

c++之理解自旋锁

什么是自旋锁

自旋锁指的是当一个线程在获取锁的时候,如果锁已经被其他线程所获取,那么该线程就将进入一个循环,不断的去判断自身是否能够获得锁 ,直到该线程获得了锁,线程才会退出循环。

自旋锁与互斥锁一样是一个为了实现对共享资源的保护而提出的锁机制,都是为了解决对某项资源的互斥使用,它们保证了在并发过程中,该共享资源在任意一个时间端都只有一个拥有者,但是与互斥锁不同的是,自旋锁在共享资源已经被占用的情况下,该线程不会进入阻塞状态,如果自旋锁已经被其他线程所占有,此时试图调用自旋锁将进入循环状态来查看是否能不能获得该锁,而这本身也是由于两者在调度机制上有所不同所造成的。

注意: 未获取锁的线程一直没有休眠处于活跃状态,虽然它本身并不执行什么工作,但是它依旧会消耗cpu,我们称这种状态叫busy waitting

示例代码

#include <iostream>
#include <atomic>
#include <thread>

using namespace std;

class CAS
{
private:
    std::atomic<bool> flag;
public:
    CAS():flag(false){}
    CAS(const CAS&)=delete;
    CAS& operator =(const CAS&)=delete;
    
    void lock()
    {
        bool expect=false;
        while(!flag.compare_exchange_strong(expect,true)) //判断能否获得锁
        {
            expect=false;  // 失败后,再次尝试
        }
    }

    void unlock()
    {
        flag.store(false);   //解锁
    }
};

int sum=0;
CAS cas;

void fun()
{
    for(int i=0;i<10;i++)
    {
        cas.lock();
        cout<<"sum:"<<sum++<<endl;
        cas.unlock();
    }
}

int main()
{
    std::thread t1(fun);
    std::thread t2(fun);
    t1.join();
    t2.join();
    return 0;
}

编译的makefile

all: demo1

demo1: 自旋锁.cpp
	g++ -pthread 自旋锁.cpp -std=c++11 -o demo1

clean:
	rm -f demo1

输出结果:

sum:0
sum:1
sum:2
sum:3
sum:4
sum:5
sum:6
sum:7
sum:8
sum:9
sum:10
sum:11
sum:12
sum:13
sum:14
sum:15
sum:16
sum:17
sum:18
sum:19

我们可以看到并不是两个线程互相干扰,而是依次递增。当获得锁的线程还未结束时,另一个线程要进入获取锁时,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,(即expect为false,flag为true,返回false,一直进入while循环),直到获取到锁才会退出循环。当一个线程退出时,另外一个在等待的线程将会立即进入,减少线程由用户态到内核态的转换。

总结

  • 自旋锁与互斥锁都是一种共享资源保护机制
  • 自旋锁的请求者状态始终为活跃的,而互斥锁则是阻塞的
  • 自旋锁如果持有锁的时间太长,则会导致其它等待获取锁的线程耗尽CPU。
  • 自旋锁本身无法保证公平性,同时也无法保证可重入性。

结语

本篇篇章有限,简单介绍一些互斥锁的使用,在下一篇文章中我们将
以日志服务部分为例,剖析以下自旋锁在多线程程序中的使用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaEE:File类查询一个文件的路径(举例+源码 )

一、File类概述 Java 中通过 java.io.File 类来对一个文件&#xff08;包括目录&#xff09;进行抽象的描述。File 类中的方法可以对文件路径以及文件名等信息进行查询&#xff0c;也可以对文件进行各项增删改操作&#xff0c;本文主要介绍 File 类的查询方法。 二、代码示例 …

计算机系统基础知识总结

一、计算机系统概述 计算系统可以分为硬件和软件两部分。硬件主要有中央处理器、存储器、输入和输出设备组成&#xff1b;软件由系统软件和应用软件组成。 冯诺依曼计算机体系&#xff1a;将硬件划分为&#xff1a;输入、输出、运算器、存储器、控制器五部分。 中央处理器&…

【WP】猿人学4 雪碧图、样式干扰

https://match.yuanrenxue.cn/match/4 探索 首先打开Fiddler&#xff0c;发现每个包的除了page参数一样&#xff0c;然后重放攻击可以实现&#xff0c;尝试py复现 Python可以正常拿到数据&#xff0c;这题不考请求&#xff0c;这题的难点原来在于数据的加密&#xff0c;这些数字…

什么是301重定向,什么时候应该使用?301重定向详细说明

如果您将网站从一个URL移动到另一个URL&#xff0c;您需要采取必要的步骤来确保您的访问者被发送到正确的位置。在技术领域&#xff0c;这被称为301重定向。 在这里&#xff0c;我们将讨论什么是301重定向&#xff0c;何时需要使用&#xff0c;以及如何在网站或WordPress中重定…

网络流的C++代码实现与过程讲解

网络流是一种非常重要的图论算法,它在许多实际问题中得到广泛应用。本文将介绍网络流算法的C++代码实现与过程讲解。 算法概述 网络流算法是通过将图中的边看作流量通道,将图的点看作流量的起点或终点,来求解图中的最大或最小流量的问题。它是一种非常重要的最优化算法,广…

闲谈跨部门工作

先附上一张网络流传的IT职场江湖图 然后再来探讨一下在工作中如何跨部门沟通&#xff0c;作为一个团队leader&#xff0c;或者团队的核心开发人员&#xff0c;如何有效的跨部门沟通。 在当今快节奏的软件开发行业中&#xff0c;一个公司的组织架构必然是多样化的&#xff0c;多…

15个真正免费的Mac数据恢复软件

由于不同的情况&#xff0c;从Mac或其他存储设备丢失重要文件对我们来说确实是一个巨大的痛苦&#xff0c;但没有人可以避免。现在&#xff0c;您丢失了宝贵的数据&#xff0c;如何找回它&#xff1f; 如果您始终备份数据&#xff0c;则可以从 Time Machine 或其他备份位置恢复…

邮箱签名有什么用?管理员怎么统一设置邮箱签名?

电子邮箱签名能够为个人随意设置&#xff0c;但对企业来说&#xff0c;职工签名代表企业形象&#xff0c;好的公司签名能够反映企业标准化和统一。那样&#xff0c;企业管理员怎样设置统一的签名呢&#xff1f;下面小编将带您深入了解。 一、邮箱签名的功能和作用 在发邮件时…

混合app开发

安卓与h5交互 原生调用js js调用原生 ios与h5交互 代码演示 ios调用h5 xcode创建一个ios项目 h5调用原生 h5部分代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" conten…

pygame 烟花效果

# 初始化 pygame.init() screen_width 800 screen_height 600 screen pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption(烟花效果) # 焰火发射 particles [] # 焰火粒子 def firework(x, y): num_particles 100 # 每次发射的…

华为云服务镜像手动更换

操作步骤&#xff1a; 1、进入华为云首页点击云容器引擎CCE&#xff1b; 2、选择你所要更换镜像的环境【这里以dev环境演示】&#xff1b; 3、点击dev环境后选择顶部的命名空间&#xff0c;点击【工作负载】中右侧栏的【升级】按钮&#xff1b; 4、点【更换镜像】选择你在test…

三级等保安全解决方案——实施方案

实施方案设计 本方案将依照国家有关信息安全建设的一系列法规和政策&#xff0c;为电台建立体系完整、安全功能强健、系统性能优良的网络安全系统。以“统一规划、重点明确、合理建设、逐步强化”为基本指导原则。根据电台网络系统不同信息的重要性调整保护策略&#xff0c;不欠…

06-vscode+espidf开发调试方法(内置JTAG调试)

使用VS Code和ESP-IDF进行ESP32开发和调试 在我们搭建 IDF 框架后&#xff0c;OpenOCD 已经自动下载好了&#xff0c; 我们通过 JTAG 接口连接使用 OpenOCD 进行调试。而ESP32芯片中内置 了JTAG 电路&#xff0c;无需额外芯片即可调试&#xff0c;更加方便&#xff0c;所以这里…

ubuntu下交叉编译ffmpeg到目标架构为aarch架构的系统

Ubuntu下FFmpeg的aarch64-linux-gnu架构交叉编译教程 一、前言 有时候真的很想报警的&#xff0c;嵌入式算法部署花了好多时间了&#xff0c;RKNN 1808真是问题不少&#xff1b;甲方那边也是老是提新要求&#xff0c;真是受不了。 由于做目标检测&#xff0c;在C代码中有对视…

Maven的dependencyManagement与dependencies区别

先说结论&#xff1a;Maven 使用dependencyManagement 元素来提供了一种管理依赖版本号的方式。 在maven多模块项目的pom文件中&#xff0c;有的小伙伴会发现最外层的pom文件和里面的pom文件有个地方不一样 如下图 父pom 子pom 一般来说是在maven的最外父工程pom文件里&…

压缩感知的概述梳理(4)

参考文献 A novel triple-image encryption and hiding algorithm based on chaos, compressive sensing and 3D DCT 文献内容 分析 结构 压缩感知 (CS) 的核心要素与流程 信号 x 长度&#xff1a;N表示法&#xff1a;(x \sum_{i1}^N u_i s_i) (u_i)&#xff1a;正交基的第…

阿里云服务器上配置Docker 以及常用命令讲解

目录 一、认识docer二、在阿里云服务器上配置Docker三、底层原理4、常用命令&#xff08;1&#xff09;Docker中常见镜像命令&#xff08;2&#xff09;Docker中常见容器命令&#xff08;3&#xff09;日志查看命令&#xff08;4&#xff09;进入容器的命令与拷贝命令 一、认识…

Docker容器嵌入式开发:在Ubuntu上配置RStudio与R语言、可视化操作

目录 一、dirmngr工具二、R环境安装与配置三、验证是否安装成功四、安装Rstudio五、可视化操作参考 以上是在Ubuntu 18.04上安装最新版本的R语言环境的步骤摘要。首先&#xff0c;通过添加CRAN镜像源并安装GPG密钥来配置软件源。然后&#xff0c;更新软件包列表并通过apt安装R语…

svn使用(上传自己的项目到svn上)

安卓开发工具版本 创建项目后&#xff0c;首先在.gitgnore文件里面加入你要过滤的文件路径 然后点击VCS——》share Project&#xff0c;然后下一步选择一个svn路径&#xff0c;点击确定后。然后将代码提交。

团体程序设计天梯赛 往年关键真题 详细分析完整AC代码】L2-014 列车调度 STL L2-015 互评成绩 排序

【团体程序设计天梯赛 往年关键真题 详细分析&完整AC代码】搞懂了赛场上拿下就稳 【团体程序设计天梯赛 往年关键真题 25分题合集 详细分析&完整AC代码】&#xff08;L2-001 - L2-024&#xff09;搞懂了赛场上拿下就稳了 【团体程序设计天梯赛 往年关键真题 25分题合…
最新文章