手写一个锁其实也很easy

懵逼的状态:    

         面试中经常被问到,如何手写一个锁,很多时候一脸懵逼,不知所措,多少年前深有体会,然而回过头来细细分析,只需使用AtomicReference类 即可以轻松搞定。首先咱们先来了解一下AtomicReference。

 AtomicReference:

一. AtomicReference 隶属Atomic家族,可以作用于普通对象,保证更新和访问引用对象操作的原子性。

  • 主要方法

compareAndSet(V expect, V update)基于原子性操作,如果当前值等于期待的值(expect)则更新成新值(update)返回true, 否则返回失败。
getAndUpdate(UnaryOperator<V> updateFunction)传入UnaryOperator函数,基于原子性操作,自旋判断期待的值是否等于上一个的值(get() 方法获取),如果相等则更新为UnaryOperator函数apply 方法 传入的值,并返回上一个值.
get()返回当前的值
updateAndGet(UnaryOperator<V> updateFunction)原理同getAndUpdate(),只是如果更新成功返回更新后的值
set(V newValue)设置当前的值

  • 底层原理

        实现原子性操作:如果匹配期待的值(except)则更新成新值(update)。 CAS 机制需要3个操作值:

    a:需要读写变量的内存位置 V;

    b:旧的预期值 A;

    c:准备设置新值 B;

         通过原子性操作,如果旧的值匹配A则更新成B否则不更新,一般结合自旋模式,不断尝试重复执行这个流程,直到更新成功。


public final boolean weakCompareAndSet(V expect, V update) {return unsafe.compareAndSwapObject(this, valueOffset, expect, update);}

二. 使用AtomicReference 手写锁,基于CAS 机制实现

  1.      模拟5个线程竞争获取锁,通过compareAndSet方法匹配当前线程如匹配成功,则表示获取锁成功,具体代码如下:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;/*** @description: TODO* @author: ppx* @date: 2023/8/1 10:08* @version: 1.0*/
public class MyCustomLock {private final static AtomicReference<Thread> reference = new AtomicReference<>();/*** @description:  获取获得锁* @param:* @return: void* @author: ppx* @date: 2023/8/1 14:41*/public void lock() {Thread currentThread = Thread.currentThread();System.out.println(currentThread.getName() + ",尝试获得锁");//通过cas 机制 自旋尝试获取锁while (!reference.compareAndSet(null, currentThread)) {// System.out.println(currentThread.getName() + "自旋尝试去获得锁wait......");}// 执行到,证明已获取到锁System.out.println(currentThread.getName() + ",已获得锁");}/*** @description:  释放锁* @param:* @return: void* @author: ppx* @date: 2023/8/1 14:42*/public void unlock() {Thread currentThread = Thread.currentThread();//通过cas 机制 自旋匹配当前线程while (!reference.compareAndSet(currentThread, null)) {}System.out.println(currentThread.getName() + ",已释放锁");}/*** @description:  模拟5个线程 竞争获取锁* @param: args* @return: void* @author: ppx* @date: 2023/8/1 14:45*/public static void main(String[] args) {MyCustomLock lock = new MyCustomLock();for (int i = 1; i < 6; i++) {new Thread(() -> {lock.lock();try {System.out.println(Thread.currentThread().getName() + " ,业务处理...");TimeUnit.SECONDS.sleep(1);} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}, "线程" + i).start();}}
}

执行结果:


线程1,尝试获得锁
线程3,尝试获得锁
线程2,尝试获得锁
线程1,已获得锁
线程4,尝试获得锁
线程5,尝试获得锁
线程1 ,业务处理...
线程1,已释放锁
线程2,已获得锁
线程2 ,业务处理...
线程2,已释放锁
线程4,已获得锁
线程4 ,业务处理...
线程4,已释放锁
线程3,已获得锁
线程3 ,业务处理...
线程3,已释放锁
线程5,已获得锁
线程5 ,业务处理...
线程5,已释放锁

实现一个锁,如此Easy。

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

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

相关文章

数据截断、频谱泄漏与窗函数的选择

目录 数据截断、频谱泄漏与窗函数的选择 什么是频谱泄漏&#xff1f; 解决频谱泄漏问题的方法 主瓣和旁瓣 窗函数介绍 窗函数解决频谱泄漏问题的原理 窗函数的种类、特点和如何使用 1、矩形窗 2、三角窗 3、汉宁窗 4、海明窗 5、布莱克曼窗 6、巴特窗&#xff1a;…

opencv 31-图像平滑处理-方框滤波cv2.boxFilter()

方框滤波&#xff08;Box Filtering&#xff09;是一种简单的图像平滑处理方法&#xff0c;它主要用于去除图像中的噪声和减少细节&#xff0c;同时保持图像的整体亮度分布。 方框滤波的原理很简单&#xff1a;对于图像中的每个像素&#xff0c;将其周围的一个固定大小的邻域内…

MySQL安装 找不到 MSVCP100.dll

安装mysql5.6.51时&#xff0c;出现由于找不到 MSVCP100.dll&#xff0c;无法继续执行代码。重新安装程序可能会解决此问题。 这应该是缺少VS运行库文件导致的&#xff0c;运行库就是支持大部分程序运行的基础&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编…

刷题笔记 day2

力扣 1089 复写零 思路&#xff1a;双指针 第一步&#xff1a;利用指针 cur 去记录最后一位要复写的数 &#xff0c; 利用指针 dest 指向最后一位数所要复写的位置&#xff1b; 实现过程&#xff1a;最开始 cur 指向0&#xff0c;dest 指向 -1 &#xff0c; 当arr[cur] ! …

【UEC++学习】UE网络 - Replication、RPC

1. UE网络架构 &#xff08;1&#xff09;UE的网络架构是SC&#xff08;Server - Client&#xff09;的模式&#xff0c;这种模式的优势&#xff1a;这种模式让所有客户端都在服务器端进行安全验证&#xff0c;这样可以有效的防止客户端上的作弊问题。 &#xff08;2&#xff…

Python(五十六)列表元素的排序操作

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

数据结构初阶--栈和队列

目录 一.栈 1.栈的定义 2.顺序栈的功能实现 2.1.顺序栈的定义 2.2.顺序栈的初始化 2.3.顺序栈的判空 2.4.顺序栈的入栈 2.5.顺序栈的出栈 2.6.顺序栈的取栈顶元素 2.7.顺序栈的求栈的大小 2.8.顺序栈的销毁 2.9.完整程序 Stack.h Stack.c test.c 二.队列 1.队…

使用 Docker Compose 部署 Redis Cluster 集群,轻松搭建高可用分布式缓存

Redis Cluster&#xff08;Redis 集群&#xff09;是 Redis 分布式解决方案的一部分&#xff0c;它旨在提供高可用性、高性能和横向扩展的功能。Redis Cluster 能够将多个 Redis 节点组合成一个分布式集群&#xff0c;实现数据分片和负载均衡&#xff0c;从而确保在大规模应用场…

session反序列化+SoapClientSSRF+CRLF

文章目录 session反序列化SoapClientSSRFCRLF前言bestphps revengecall_user_func()方法的特性SSRFCRLF组合拳session反序列化 解题步骤总结 session反序列化SoapClientSSRFCRLF 前言 从一道题分析通过session反序列化出发SoapClientSSRF利用CRLF解题 bestphp’s revenge 首…

基于方向编码的模板匹配算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ........................................................................... %选择移动个…

自适应巡航控制系统研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 据统计, 我国交通事故造成的伤亡人数每年超过10万人, 其中驾驶员人为原因 (疲劳、酒驾、误操作等) 所致事故逐渐升高.汽车交通…

pycharm——制作k线图

K 线图 Candlestick Candlestick - Kline_itemstyle from pyecharts import options as opts from pyecharts.charts import Klinedata [[2320.26, 2320.26, 2287.3, 2362.94],[2300, 2291.3, 2288.26, 2308.38],[2295.35, 2346.5, 2295.35, 2345.92],[2347.22, 2358.98, 23…

安装skywalking并集成到微服务项目

文章目录 一、前言二、介绍1. 架构 三、安装skywalking服务端四、启动skywalking服务端五、微服务项目开发注册中心网关服务商品服务订单服务支付服务测试 六、下载java客户端七、微服务集成skywalking客户端1. idea启动2. 命令行启动3. 集成效果 八、skywalking客户端配置1. 配…

Python高阶技巧 正则表达式

正则表达式&#xff0c;又称规则表达式&#xff08;Regular Expression&#xff09;&#xff0c;是使用单个字符串来描述、匹配某个句法规则的字符串&#xff0c;常被用来检索、替换那些符合某个模式&#xff08;规则&#xff09;的文本。 简单来说&#xff0c;正则表达式就是使…

小程序学习(六):全局配置

1.全局配置文件及常用的配置项 全局配置-window 2.小程序窗口的组成部分 3.了解window节点常用的配置项 4.设置导航栏的标题 设置步骤:app.json->window->navigationBarTitleText 5.设置导航栏的背景色 背景颜色不支持red这种文字 6.设置导航栏的标题颜色 注意:navigat…

SpringBoot笔记:SpringBoot集成Dataway

文章目录 1、什么是 Dataway?2、主打场景3、技术架构4、整合SpringBoot4.1、maven 依赖4.2、初始化脚本4.3、整合 SpringBoot 5、Dataway 接口管理6、Mybatis 语法支持7、小结 1、什么是 Dataway? 官网地址&#xff1a;https://www.hasor.net/docs/guides/quickstart Da…

k8s kubeadm命令升级集群 从1.17升级到1.18

k8s kubeadm命令升级集群 从1.17升级到1.18 大纲 注意事项master节点执行升级命令master节点和node节点执行命令 注意事项 目标当前线上k8s集群版本是k8s1.17 想把k8s升级到1.18。注意k8s不能跨版本升级例如k8s1.17不能直接升级到k8s1.19&#xff0c;需要先升级到1.18才后向…

faac内存开销较大,为方便嵌入式设备使用进行优化(valgrind使用)

faac内存开销较大&#xff0c;为方便嵌入式设备使用进行优化&#xff0c;在github上提了issues但是没人理我&#xff0c;所以就搞一份代码自己玩吧。 基于faac_1_30版本&#xff0c;原工程https://github.com/knik0/faac faac内存优化: faac内存开销较大&#xff0c;为方便嵌入…

意外:WPS编程新工具,不用编程,excel用户:可以不用VBA啦

来来来&#xff0c;拓宽一下视野&#xff01; 别总以为excel和WPS只能用VBA编程&#xff0c;也别总是想着ACCESS这些老生常谈的工具。其实对于电子表格高级用户来讲&#xff0c;不会VBA&#xff0c;不用ACCESS&#xff0c;也一样可以解决复杂问题或者高级应用。 尤其是WPS用户…

【腾讯云 Cloud Studio 实战训练营】CloudStudio体验真正的现代化开发方式,双手插兜不知道什么叫对手!

CloudStudio体验真正的现代化开发方式&#xff0c;双手插兜不知道什么叫对手&#xff01; 文章目录 CloudStudio体验真正的现代化开发方式&#xff0c;双手插兜不知道什么叫对手&#xff01;前言出现的背景一、CloudStudio 是什么&#xff1f;二、CloudStudio 的特点三、CloudS…