java的锁synchronied和本地锁(reentrantLock)与分布式锁(redisson)的底层实现

ReentrantLock详解(可重入、可中断、锁超时、公平锁、条件变量)、同步模式之顺序控制 文章目录1.ReentrantLock详解1.1 可重入1.2 可中断 lockInterruptibly()1.3 设置超时时间 tryLock()1.4 通过lock.tryLock()来解决, 哲学家就餐问题1.5 公平锁 new ReentrantLock(true)1.6 条件变量 Condition 1.ReentrantLock详解 相对于synchronized 它具备如下特点 可中断 可以设置超时时间 可以设置为公平锁 支持多个条件变量 与 synchronized 一样,都支持可重入 阅读详情

Synchronized锁

synchronized锁有什么特性,怎么解决并发问题

解决可见性问题

屏障-monitorenter-读屏障 保证读取到的数据都是最新的,monitorExit-写屏障 保证数据都写入到主存中。

解决原子性问题

锁的特性,只有获取锁的线程,才能执行代码。保证操作的原子性。

synchronized是怎么去优化性能的

锁升级的过程 - 更具并发的场景,采用不同的加锁方式。(重量级锁,需要使用操作系统的mutex,涉及用户态和内核态的切换。 所以在锁竞争少的情况下,使用其它的加锁方式)

偏向 -》轻量:有第二线程尝试获取锁,可自旋等待

轻量-》重量:第二个线程自旋一段时间依然没有获取到锁。或者有更多的线程来抢锁,那就升级为重量级锁。(核心原则:短时间自旋的效率优于阻塞线程)

锁监视器是什么

升级为重量级锁后,对象头的mark world 会有指针指向锁监视器。

作用:记录锁的拥有者,记录锁的加锁次数,记录等待池(调用wait方式,出于等待状态的线程)和阻塞池(竞争锁失败的线程)

synchronized怎么实现的锁的自旋,阻塞,可重入

自旋:while循环,短时间性能好。长时间耗cpu。

阻塞:使用操作系统的mutex指令

可重入:基于锁监控器中的持有锁线程和加锁次数

ReentrantLock

实现原理

通线程变量记录持有锁的线程。

再通过使用voletile修饰的int变量state表示加锁状态,已经可重入锁的次数

再通过AQS的先进先出队列来实现阻塞线程的存储,实现公平锁的特性

阻塞实现:通过LockSupport.park, 将线程置为waiting状态

锁释放:当持有线程的锁释放锁时,会通过LockSupport.unpark

参考美团文章:

从ReentrantLock的实现看AQS的原理及应用 - 美团技术团队

公平锁和非公平锁相同之处

都会使用到等待队列,并且队列中,先来的线程会优先获取到锁资源。所以其实就算是非公平锁,等待队列中的线程也还是公平的。

排队队列,使用的是双向链表的结构。

公平锁和非公平锁不同之处

hasQueuedPredecessors 实现的效果是。如果等待队列中有值,那么尝试当前线程,不能直接去获取锁资源。需要加入等待队列中排队。

结论:reentrantLock的非公平锁,对于等待中的线程也是有个公平的机制的,只是没有控制新来的线程(无锁状态下,可以直接尝试获取锁)。而公平锁解决了这个问题(无锁状态下,也不能直接获取锁,需要加入等待队中排队;除非等待队列为空,才能直接尝试获取)。

补充下:

ReentrantLock获取锁的方法有好几个,每个都有一点小差别,但是整体实现思路差不多。

lock方法:会一直尝试获取锁资源。

trylock方法不加时间:只会尝试一次获取锁资源。拿不到,就返回失败。没有使用到队列。

trylock加时间:一段时间内获取不到锁资源会失败。如果截止时间到现在的时间是大于1微秒的,则线程休眠(基本上就是休眠了),否则继续尝试获取。

读锁和写锁的底层实现

首先明确下读写锁的实现效果:

读读不互斥;读写互斥;

写写互斥;写读互斥;

总结:读写场景互斥。但是读场景下的读操作不互斥,写场景下的写操作之间互斥。

实现原理:

读锁使用的共享锁;写锁使用的是排他锁。

正常情况下,共享锁和排他锁不能同时存在,这样就可以实现读写场景互斥。(但是如果是同一线程,同时持有读写锁是可以的)

共享锁,允许多个线程同时持有。可以实现,读场景下的读线程之间不互斥的效果。

排他锁,不允许多个线程同时持有。可以实现,写场景下的写线程之间互斥的效果。

下面可以看看代码是如何实现的。

如果不能获取到锁资源会怎么处理?

和上面一样。读写锁也支持公平和非公平两种模式。

redisson

1. redisson如何实现尝试获取锁的逻辑

  • 如何实现在一段的时间内不断的尝试获取锁
    • 其实就是搞了个while循环,不断的去尝试获取锁资源。但是因为latch的存在会在给定的时间内处于休眠状态。
    • 这个事件,监听的是解锁动作,如果解锁动作发生。会调用latch.release方法,这样while循环又可以重新启动,去尝试获取锁资源了。(相比单纯的轮训,避免了对cpu资源的浪费。通过信号通知,避免了没必要的轮训)
  • 尝试获取锁的过程是怎样的?
    • 使用了redis脚本执行的方式。因为存在根据查询结果,来决定执行什么变更动作。所以一定要保证动作串行执行。如果key不存,则新增key和param(线程id+redisClientid)记录,value为数值型,value=1。  如果,key + param存在,则表名key已被默认线程持有,并且这个线程就是当前线程。如果,key + param不存在,则表明key已被默认线程持有,并且这个线程不是当前线程。

2. redisson释放锁的逻辑如何实现

因为加锁时,会设置过期时间。所以就算不主动解锁。key过期了就相当于解锁了。

redisson的解锁过程如下图。先判断线程是否持有该锁。如果有,则value值减1。然后判断value是否大于0,如果大于0,则给key设置一个默认的过期时间30秒;如果等于0,则可以删除key和发布一个key删除事件。

3. redisson释放锁时,如何唤起其它线程取争抢锁

很简单,使用发布订阅的机制。

释放锁时,发布锁释放消息。由于,争抢锁的线程在之前就订阅了这个消息。所以在接收到锁释放的消息后,就会立即再次尝试获取锁资源。

4. redisson如何解决A线程加锁,但是B线程去释放锁的问题

redi支持key+param的方式进行匹配。这里的param有点像标签。当线程A获取到redis的锁资源后,会将param设置为线程id+redisson连接管理器id。然后解锁的时候,也是需要带上parma匹配的。匹配不上是解锁不了的。
redis.call('hexists', KEYS[1], ARGV[2])

5. redisson如何实现公平锁?

这里使用了和ReentrantLock一样的思路,使用了等待队列。

大概的逻辑:

1. 如果当前不是加锁状态,并且等待队列是空。则当前线程可以直接获取锁。

2. 如果当前不是加锁状态,但是等待队列不为空。则当前线程需要加入等待队列中,排队获取锁。

3. 等待中的线程如何被唤醒。依然是通过消息通知的方式。在公平锁时,需要从队列头取出线程id,只有当前线程和取出的线程id匹配才能执行,否则继续休眠。

可以看看这段代码:org.redisson.RedissonFairLock#tryLockInnerAsync

6. redisson如何实现读写锁?

读锁加锁过程

读锁释放过程

写锁的获取过程

写锁的释放过程

7. redisson的锁如果是自己过期的,是怎么唤醒其他等待线程的?

redis是有key过期事件这样的特性的。当锁的过期时间到期,Redis 会触发一个事件通知,然后 Redisson 的订阅者会接收到这个通知。并唤醒订阅的线程。

总结

读锁获取过程

读锁释放过程

写锁获取场景

写锁释放

公平锁的实现方式

8. redisson是如何实现分布式的key续期的

使用一个看门狗机制,其实就是一个延时任务,去check客户端持有的key,如果存在就将key的过期时间设置为30秒,然后再生成一个10秒后的延时任务,任务这块会使用线程池处理(默认值16)。这样就不用担心因为客户端宕机导致锁一直释放不了。

9. 分布式锁怎么实现?

首先什么是锁

我们这块说的说指的是独占锁,具有互斥性,一个线程获取到锁,另外的线程就获取不到锁。

加锁的过程,保证原子性

方法1:使用setnx

方法2:使用lua脚本

解锁过程

为保证线程释放错锁,解锁前需要判断线程是否持有该锁,依赖redis的param参数实现(线程id+redisson连接管理器id)

锁阻塞如何实现

使用AQS阻塞队列,获取不到锁的线程进入等待列中排队。当持有锁的线程释放锁时,再通过消息通知的方式环形队列头部的线程。

怎么实现可重入锁

可重入锁,说的是持有锁的线程,多次尝试获取同一把锁。可以在尝试获取锁时,check持有锁的线程id,如果是同一个线程,加锁次数加1。 在释放锁时,也是释放一次,加锁次数减1。 减到0,表示持有锁的线程,释放了锁资源

怎么解决服务宕机后,锁无法释放的问题

获取锁时,默认都会加一个过期时间。然后通过延时任务的方式进行续期。宕机后延时任务都不存在了,肯定是不会续期了。但是如果是加锁线程中断后,没有释放锁,会导致,分布式锁,一直被无效续期,所以解锁动作一定要做finally代码块中执行。

10. 看门狗线程是个什么样的线程

可以理解成一个守护线程(使用延时任务实现),定时给key续过期时间。当锁释放后,延时任务不在执行。redission中执行延时任务的是一个线程数为16的线程池。

12. redis主从架构带来的锁丢失问题怎么解决?

红锁,会尝试所有的锁,但只要获取到多数锁就算获取成功。但是按红锁多少锁的原理,发生主从替换时,依然是会有问题的。但是发生的概率会很小(正常情况下,会拿到所有的锁,只拿到半数+1的锁的情况还是非常小的,解决了绝大数场景下锁丢失的问题)。可以使用联锁的方式解决。 你可能会担心加锁的时效和主节点宕机的问题。网络波动和主节点宕机,会造成很多的业务问题。个人感觉还好。

其它问题:

1. 当然红锁还是会有不同主节点的时钟问题

2. 系统阻塞导致锁未被续期,直接被释放

但是, redisson官方其实是已经废弃了红锁机制的。

原因:多数锁依然有锁丢失问题,第二无法控制不同的锁在不同的节点,也就是说有可能出现在单一节点。

Redisson 分布式锁源码 09:RedLock 红锁的故事_Java_程序员小航_InfoQ写作社区

其实可以不用把这个问题看的过重。 首先有并发也不一定有并发问题,且在叠加主从替换的场景概率是很低的。可以考验,如果有并发问题发生,怎么去发现,然后再采用一些修正的方法来保证最终一致性。

Redisson(2-2)分布式锁实现对比 VS Java的ReentrantLock之带超时时间的tryLock Redisson实现了一整套JDK中ReentrantLock的功能,这里对比一下实现的差异和核心的思想。 unfair模式的带超时时间的tryLock(超时时间) ReentrantLock 这里上来会直接先试下能不能try成功,如果不成功,进入等待并开始竞争等逻辑。 整个锁的核心是通过LockSupport的park方法来实现的,这是调用底层UNSAFE的park方法来实现... 阅读详情

相关推荐

(详细教程)opencv+pycharm+笔记本摄像头 做一个人脸识别

文章目录 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结 一、安装opencv-python 这里推荐使用pycharm直接安装opencv-python 打开文件——设置——python解释器——点击+号 搜索opencv-python,点击安装包,等待片刻即可安装好 检查是否安装好,新建一个项目输入以下代码,若无报错则安装好 import cv2 二、准备分类器 咱们使用opencv官方提供的分类器,包括面部识别,侧...

qq_52852432的博客 1万+

ReentrantLock详解

ReentrantLock使用,

weixin_56738054的博客 1万+

prometheus 从入门到精通(史上最全)

Prometheus(由go语言开发)是一套开源的监控&报警&时间序列(按照时间排序)数据库的组合。因为kubernetes(俗称k8s)的流行带动了prometheus的发展。它可以监控主机,服务,容器,支持多种exporter采集数据,还支持pushgateway进行数据上报,Prometheus性能足够支撑上万台规模的集群。原文链接:https://blog.youkuaiyun.com/qq_45277554/article/details/130917620时间序列数据。

流水_鱼鱼的博客 1万+

ReentrantLock锁

1. 简介 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制。它可以等同于 synchronized 的使用,但是 ReentrantLock 提供了比 synchronized 更强大、灵活的锁机制,可以减少死锁发生的概率

weixin_46121031的博客 7641

logisim计组实验八 乘法器

原理:点这里 有问题欢迎留言哦~ 文章目录五位阵列乘法器电路图时间延迟分析六位补码阵列乘法器五位无符号乘法流水线原理图电路图原码一位乘法器原理图电路图补码一位乘法器 五位阵列乘法器 电路图 此处注意:全加器FA的cout端是进位端而非输出端 使用硬件控制比循环累加的速度快得多。 但是存在串行进位链 改进版: 时间延迟分析 T是计算相加数的一级门延迟 3n–>2n 性能差别在1.5倍 ...

treblez's blog 2万+

11.嵌入式控制器EC实战 KBC矩阵键盘Keyboard开发流程

文章目录笔记本矩阵键盘概述矩阵键盘的扫描方式行列扫描方式逐行逐列扫描方式EC中矩阵键盘是如何扫描并得到码值的(代码分析) 笔记本矩阵键盘概述 在EC中支持两种形式的键盘,一种是PS/2接口的键盘,这种键盘几乎已经被USB接口的键盘所取代,所以PS/2接口的键盘不在我们的讨论范围。 另一种键盘则是矩阵键盘,也是笔记本电脑的内置键盘,该键盘类似于学习单片机时使用的4*4的那种键盘,笔记本使用的矩阵键盘有三种规格,分别是16*8、17*8和18*8。16、17和18代表着该款键盘的列数,8代表着键盘的行数,我们这

qq_30135687的博客 3809

【面试必问系列】之ReentrantLock详解

的队列,可以用于构建锁的基础框架,内部通过原子变量state来表示锁的状态,当state大于0的时候表示锁被占用,如果state等于0时表示没有占用锁,ReentrantLock是一个重入锁,表现在state上,如果持有锁的线程重复获取锁时,它会将state状态进行递增,也就是获得一个信号量,当释放锁时,同时也是释放了信号量,信号量跟随减少,如果上一个线程还没有完成任务,则会进行入队等待操作。而用synchronized修饰的话,当一个线程处于等待某个锁的状态,是无法被中断的,只有一直等待下去。

一个喜欢诗和远方的程序媛 8291

Xilinx平台SRIO介绍(一)RapidIO协议介绍

菜鸟到老鸟:会用工具; 老鸟到大佬:深入理解原理。 ——FPGA大叔·沃自己硕得

数字IC/FPGA杂货铺,找一找,或许有你想要的~ 1万+

ReentrantLock介绍及使用(超详细)

1. Reentrantlock介绍及使用 2. 公平锁和非公平锁 3. Reentrantlock的使用案例 4. Reentrantlock使用时注意事项

Mr.绵羊的知识星球 2万+

27930-2015+充电协议解析

对2015+充电与2015充电进行硬件电路对比、通信协议对比和2015+通信协议解析。

manjixingkong1234的专栏 232

【云原生技术】云计算与网络:容器服务(Tencent Kubernetes Engine,简称TKE)简介

基本概念主要特点应用场景技术实现容器服务(Tencent Kubernetes Engine,简称TKE)是腾讯云提供的一种托管的容器管理服务,基于开源的Kubernetes系统。TKE旨在简化容器的部署、管理和扩展,并且提供高性能、可靠性和安全性,适用于各种规模的企业和应用。

weixin_46453070的博客 2043

ReentrantLock 锁详解

ReentrantLock 支持公平锁和非公平锁,可重入锁 ReentrantLock的底层是通过 **AQS[链接]**实现。 一、BAT 大厂的面试题 **【1】**什么是可重入,什么是可重入锁? 它用来解决什么问题? 【2】ReentrantLock 的核心是 AQS,那么它怎么来实现的,继承吗? 说说其类内部结构关系。 【3】ReentrantLock 是如何实现公平锁的? 【4】ReentrantLock 是如何实现非公平锁的? 【5】ReentrantLock 默认实现的是公平还是非公平锁.

m0_37235955的博客 3692

【RT-DETR涨点改进】独家创新改进篇 | AAAI2024 | RT-DETR引入CFBlock增强对长程依赖和全局语义信息的建模能力,有助于提升复杂场景下小目标、遮挡目标的检测精度

本文给大家介绍在RT-DETR中引入CFBlock模块,能够有效提升模型对长程依赖和全局语义信息的建模能力,在保持轻量化和高效推理的基础上增强特征表达力,特别有助于提升复杂场景下小目标、遮挡目标的检测精度,从而实现更优的精度与速度平衡。

Ai缝合怪、助力小伙伴高效发论文 259

ReentrantLock并发锁使用详解

进入源码可以看到,其实现了公平锁和非公平锁内部实现了加锁的操作,并且支持重入锁。不用我们再重写解锁操作。

Huangjiazhen711的博客 1742

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Java:Java学习笔记之ReentrantLock的简单理解和使用

ReentrantLock ReentrantLock1、相关知识1.1 公平锁和非公平锁1.2 可重入锁1.3、CAS算法2、背景、定义和特征2.1、背景2.2、定义2.3、特征3、基本结构4、基本使用4.1、解决背景问题4.2、重入锁 使用4.3、公平锁使用5、源码分析5.1、AQS5.2、非公平锁的实现原理5.2.1、lock方法获取锁:tryAcquire5.2.2、锁的释放:tryRelease5.3、公平锁的实现原理5.3.1、lock方法获取锁:tryAcquire5.3.2、锁的释放:try

JMW1407的博客 6989

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

redisson使用全解——redisson官方文档+注释(中篇)

接上篇redisson使用全解——redisson官方文档+注释(上篇)基于Redis的Redisson分布式可重入锁RLock Java对象实现了java.util.concurrent.locks.Lock接口。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。 大家都知道,如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在R

秃了也弱了 5万+

ReentrantLock简单理解

ReentrantLock

qq_36138652的博客 2676

Java 中的Lock锁对象(ReentrantLock/ReentrantReadWriteLock)详解

当有线程获取读锁时,如果当前没有线程持有写锁,则读锁将立即被获取,读锁计数器加一,表示当前有一个线程持有读锁。在 getValue() 方法中,线程会获取锁,返回共享变量 value 的值,最后释放锁。例如,如果一个线程在尝试获取锁的过程中遇到了饥饿现象(即一直获取不到锁),那么系统可能会采用类似于睡眠的方式,让该线程暂时让出 CPU 资源,等待一段时间后再次尝试获取锁。接着,它获取读锁,释放写锁,这样就实现了锁降级。这是因为写锁是独占锁,不能被多个线程同时持有,而读锁是共享锁,可以被多个线程同时持有。

swadian2008的博客 4022

Synchronize 和 Lock (ReentrantLock)的区别

一、synchronized和lock的用法区别 synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。 lock:需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。 用法区别比较简单...

jim_007的博客 1932

并发编程:synchronized和ReentrantLock的区别与底层原理

1.都是用来协调多线程对共享对象、变量的访问2. 都是可重入锁,同一线程可以多次获得同一个锁3. 都保证了可见性和互斥性(syhronize本身就具有可见性,ReentrantLock底层写了volatile来保证可见性)

xjdkxnhcoskxbco的博客 1871

ReentrantLock原理及详细的使用方法

的核心是基于AQS(抽象队列同步器)实现的。AQS 维护了一个队列,用于管理所有请求锁的线程。每个线程尝试获取锁时,如果当前锁被其他线程持有,则进入等待队列,阻塞等待锁释放。一旦锁释放,AQS 会从队列中唤醒下一个线程,允许它获取锁。提供了比更灵活的锁控制方式。选择公平锁和非公平锁;提供尝试获取锁和可中断的锁;允许锁的重入;支持手动加锁和解锁的细粒度控制。

yymagicer的博客 2345

2019.11.14学习总结

Java开发中几种常见的锁 1.公平锁 是指多个线程按照申请锁的顺序来获取资源,类似于队列,先进先出(FIFO)。 2.非公平锁 是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程先获得锁。在高并发的情况下,有可能造成优先级反转或饥饿现象。 源码: public ReentrantLock(boolean fair) { sync = fair ? new F...

qq_41641761的博客 492

ReentrantLock 基本原理

ReentrantLock底层基于AQS,其构造方法返回的就是NonfaireSync和faireSync;两种同步器都继承自Sync,Sync又继承自AQS!newReentrantLock时,返回的就是同步器,默认是非公平的;

机械工程跑路哥 3615

redisson简单介绍

1、什么是redisson   Redisson - 是一个高级的分布式协调Redis客服端,能帮助用户在分布式环境中轻松实现一些Java的对象,Redisson、Jedis、Lettuce 是三个不同的操作 Redis 的客户端,Jedis、Lettuce 的 API 更侧重对 Reids 数据库的 CRUD(增删改查),而 Redisson API 侧重于分布式开发 2、支持Redis多种连接模式 ​   1、集群模式 Config config = new Config(); confi

qq_25582465的博客 6万+
上一篇: Collections工具类整理
下一篇: 随意聊架构
带着托托写代码
博客等级 码龄10年 112粉丝 90原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值