【并发编程十四】c++原子操作(2)——实现自旋锁

news2024/12/23 12:44:01

【并发编程十四】c++原子操作(2)——实现自旋锁

  • 一、自旋锁简介
  • 二、使用自旋锁
  • 三、不使用自旋锁
  • 四、分析

  • 简介
    在介绍完原子操作,我们这篇使用c++提供的原子操作,实现一个自旋锁,并加以利用。

原子操作参见【并发编程十三】c++原子操作

一、自旋锁简介

“自旋”可以理解为“自我旋转”,这里的“旋转”指“循环”,比如 while 循环或者 for 循环。“自旋”就是自己在这里不停地循环,直到目标达成。而不像普通的锁那样,如果获取不到锁就进入阻塞

  • 自旋锁(spinlock):是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。

  • 自旋锁,它并不会放弃 CPU 时间片,而是通过自旋等待锁的释放,也就是说,它会不停地再次地尝试获取锁,如果失败就再次尝试,直到成功为止

  • 非自旋锁,非自旋锁和自旋锁是完全不一样的,如果它发现此时获取不到锁,它就把自己的线程切换状态,让线程休眠,然后 CPU 就可以在这段时间去做很多其他的事情,直到之前持有这把锁的线程释放了锁,于是 CPU 再把之前的线程恢复回来,让这个线程再去尝试获取这把锁。如果再次失败,就再次让线程休眠

非自旋锁和自旋锁最大的区别,就是如果它遇到拿不到锁的情况,它会把线程阻塞,直到被唤醒。而自旋锁会不停地尝试

二、使用自旋锁

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

using namespace std;

class spinlock_mutex
{
public:
	spinlock_mutex() {};

	//spinlock_mutex(const spinlock_mutex& origin); // add this line
	~spinlock_mutex() {};

	void lock()
	{
		while (flag.test_and_set(memory_order_acquire));
	}
	void unlock()
	{
		flag.clear(memory_order_release);
	}
private:
	atomic_flag flag = ATOMIC_FLAG_INIT;
};

int g = 0;
spinlock_mutex mtx;

void task()
{
	for (int i = 0; i < 5; i++)
	{
		lock_guard<spinlock_mutex> my_lock(mtx);
		//mtx.lock();
		g++;
		cout << "task:g="<<g << endl;
		//mtx.unlock();
	}
}

int main()
{
	//cout << "g"<<g << endl;

	thread t1(task);
	thread t2(task);

	t1.join();
	t2.join();
	return 0;
}

输出

在这里插入图片描述

三、不使用自旋锁

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

using namespace std;

//class spinlock_mutex
//{
//public:
//	spinlock_mutex() 	
//	{
//	}
//
//	//spinlock_mutex(const spinlock_mutex& origin); // add this line
//	~spinlock_mutex() {};
//
//	void lock()
//	{
//		while (flag.test_and_set(memory_order_acquire));
//	}
//	void unlock()
//	{
//		flag.clear(memory_order_release);
//	}
//private:
//	atomic_flag flag = ATOMIC_FLAG_INIT;
//};

int g = 0;
//spinlock_mutex mtx;

void task()
{
	for (int i = 0; i < 5; i++)
	{
		// lock_guard<spinlock_mutex> my_lock(mtx);
		//mtx.lock();
		g++;
		cout << "task:g="<<g << endl;

		//mtx.unlock();
	}
}

int main()
{
	//cout << "g"<<g << endl;

	thread t1(task);
	thread t2(task);

	t1.join();
	t2.join();
	return 0;
}

输出

在这里插入图片描述

四、分析

  • 因为io是进程内共享的,所以当我们操作而不加锁时,会出现输出串行的现象。(说明我们实现的自旋锁可用、有效)
  • 我们实现的自旋锁可以配合lock_guard使用;
  • 当然我们也可以直接使用mtx.lock()、mtx.unlock();进行加锁和解锁。

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

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

相关文章

什么是shell?shell在Linux内怎么编写脚本?

目录 一、概念 二、简单创建脚本 三、shell语法 1.变量 2.环境变量 3.参数变量 4.条件 5.控制结构 if语句 elif语句 for语句 一、概念 什么是shell? shell是一个作为用户与Linux系统间接口的程序&#xff0c;它允许用户向操作系统输入需要执行的命令。 下图显示了sh…

kali之setoolkit使用

kali之setoolkit使用 1 搭建钓鱼网站 钓鱼网站是黑客常用的用于盗取目标用户名与账号的方式&#xff0c;今天主要介绍setoolkit来制作钓鱼网站 setoolkit是kali下的社会工程学工具集。 ①进入setoolkit 命令行输入&#xff1a; setoolkit②选择社会工程学攻击 - 网络攻击 - …

基于Android的二手车交易系统

需求信息&#xff1a; 1、登录功能:用户可以注册登录&#xff0c;管理员可以给销售人员权限&#xff0c;所以销售人员只能登陆。 2、维护车辆信息:主要实现的是客户添加修改查询删除车辆信息&#xff0c;然后发布车辆需要提交&#xff0c;提交给管理员&#xff0c;管理员审核了…

四、Executor执行器【无标题】

Executor Executor 接口定义了数据库操作的基本方法&#xff0c;其中 query*() 方法、update() 方法、flushStatement() 方法是执行 SQL 语句的基础方法&#xff0c;commit() 方法、rollback() 方法以及 getTransaction() 方法与事务的提交/回滚相关&#xff0c;clearLocalCac…

Python快速入门

最近在很多地方都可以看到Python的身影&#xff0c;尤其在人工智能等科学领域&#xff0c;其丰富的科学计算等方面类库无比强大。很多身边的哥们也提到Python非常的简洁方便&#xff0c;比如用Django搭建一个见得网站只需要半天时间即可&#xff0c;因此也吸引了我不小的兴趣。…

二叉树:删除二叉搜索树中的节点

删除二叉搜索树中的结点 一、题目描述 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除…

2023牛客寒假算法基础集训营5(通过ABCDHIKL) I题有详解(F已补)

其他题待补中…… 链接&#xff1a;2023牛客寒假算法基础集训营5 简单题 A 小沙の好客&#xff08;贪心&#xff0c;前缀和&#xff0c;二分&#xff09; 题意思路 给定nnn个商品的价值&#xff0c;qqq次询问&#xff0c;每次询问k,xk, xk,x即价值不超过xxx的商品最多可以拿…

文件输入输出缓冲流IO综合练习——学生管理系统文件版

综合练习&#xff08;一&#xff09; 键盘录入3个学生信息(学号,姓名,年龄,居住城市)存入集合。然后遍历集合把每一个学生信息存入文本文件(每一个学生信息为一行&#xff0c;自己定义分割标记) 学生类&#xff1a; package com.itheima; /** 标准的学生类*/ public class St…

【数据结构 (3)】1.4 算法和算法分析

文章目录1. 算法的定义及特性算法的特性算法设计的要求2. 算法的时间复杂度分析算法时间复杂度的基本方法算法时间复杂度分析例题算法时间复杂度的计算3. 算法的空间复杂度1. 算法的定义及特性 算法的定义 对特定问题求解方法和步骤的一种描述&#xff0c;它是指令的有限序列…

WSL-Ubuntu 安装、移动

设置” 启用或者关闭Windows功能“&#xff0c;勾选如下选项。Hyper-v若存在灰色&#xff0c;可进入BIOS-Configuration&#xff0c;Intel Virtual Technology设置Enable重启2、安装Ubuntu3、移动。Ubuntu默认安装C盘。首先D盘创建移动的目录&#xff0c;例如&#xff1a;D:\Ub…

使用kubeadm搭建高可用k8s集群

使用kubeadm搭建高可用k8s集群方案选型高可用k8s集群部署准备工作服务器统一配置配置hostname打通ssh免密登录部署etcd集群step1 在master01上生成配置相关文件step2 每台服务器上启动etcd服务step3 检查etcd集群是否正常部署负载均衡 (haproxy keepalived)step1 下载haproxy与…

SAP 分析云 2023.012023.02 版新功能抢先看

大家新年好呀&#xff01;本年度的第一篇推文来啦~本文介绍了SAP 分析云2023.01&2023.02 版本的新功能。这些新功能已经在SAP 分析云FastTrack 客户的系统上线。对于 SAP 分析云季度发布周期 (QRC) 客户&#xff0c;此版本及其功能将作为 QRC 2023 年第1季度版本的一部分提…

[Android开发基础3] Activity的生命周期、创建与配置

文章目录 生命周期 概念 生命周期周期函数 创建Activity 方法一&#xff1a;编译器自动创建与配置 方法二&#xff1a;手动创建与配置 生命周期 概念 生命周期&#xff0c;顾名思义&#xff0c;就是当前的程序单元Activity从启动到销毁之间一系列所经过的状态。 生命周期周…

怎么画室内导航地图,室内地图绘制工具

现在很多楼宇建的越来越大&#xff0c;停车场、商场、展览馆、博物馆、交通枢纽等大型室内场景规模巨大、环境复杂&#xff0c;人们置身其中&#xff0c;一不小心就走错方向&#xff0c;从而多走很多弯路&#xff0c;费时费力。室内导航一直是导航场景的一大难题&#xff0c;如…

【redis6】第十四章(Redis集群)

问题 容量不够&#xff0c;redis如何进行扩容&#xff1f; 并发写操作&#xff0c;redis如何分摊&#xff1f; 另外&#xff0c;主从模式&#xff0c;薪火相传模式&#xff0c;主机宕机&#xff0c;导致ip地址发生变化&#xff0c;应用程序中配置需要修改对应的主机地址、端…

什么是Go语言?

本文首发自「慕课网」&#xff0c;想了解更多IT干货内容&#xff0c;程序员圈内热闻&#xff0c;欢迎关注&#xff01; 作者|慕课网精英讲师 Codey 1. Go 语言的出身 Go&#xff08;又称 golang&#xff09;是 Google 开发的一种静态强类型、编译型、并发型&#xff0c;并具…

OpenMMLab AI实战课笔记-第1节课

1. 第一节课&#xff08;课程链接&#xff09; 1.1 计算机视觉任务 计算机视觉主要实现以下目标&#xff1a; 分类目标检测分割&#xff1a;语义分割、实例分割 (对像素进行精确分类, 像素粒度或细粒度)关键点检测 1.2 OpenMMLab框架 框架选择&#xff1a;PyTorchOpenMML…

多级缓存案例说明

多级缓存案例说明1.安装MySQL1.1.准备目录1.2.运行命令1.3.修改配置1.4.重启2.导入SQL3.创建Demo工程3.1.分页查询商品3.2.新增商品3.3.修改商品3.4.修改库存3.5.删除商品3.6.根据id查询商品3.7.根据id查询库存3.8.启动4.创建商品查询页面4.1.运行nginx服务4.2.反向代理为了演示…

CSS网格教程:网格布局模块/网格容器/网格项目

目录 CSS 网格布局模块 网格布局 浏览器支持 网格元素 实例 Display 属性 实例 实例 网格列&#xff08;Grid Columns&#xff09; 网格行&#xff08;Grid Rows&#xff09; 网格间隙&#xff08;Grid Gaps&#xff09; 实例 实例 实例 实例 网格行&#xff0…

java基础面试题1

目录 Java语言有哪些特点 Java都有那些开发平台&#xff1f; Jdk和Jre和JVM的区别【重要】 面向对象和面向过程的区别 什么是数据结构&#xff1f;Java的数据结构有哪些&#xff1f; 1.数组&#xff1a; 2.队列 Queue 3.链表 Linked List 4.栈Stack 5.树Tree 什么是…