Lock 锁底层实现
★ 1、讲讲 Lock 锁
是一个接口,有三个实现类,分别是常用的 可重入锁,读锁、写锁
。常用的是可重入锁。
加锁使用lock() 方法,解锁使用 unlock() 方法。Lock的底层是 AQS+CAS机制 实现。
Lock 常用子类 可重入锁ReentrantLock 有两种模式, 公平锁模式、非公平锁模式
。
公平锁模式和非公平锁模应用
默认一般创建的是非公平锁,就是允许线程插队,而不是按先来后到顺序
并发量高的,非公平可能会导致线程饿死 === 做中间件,比如rocketmq 就需要关注锁公平和不公平
mq 消息队列的应用,比如网易云多个用户的评论->mq->如果是非公平锁,那么导致线程饥饿,导致等待时间过长-不稳定
解决:mq源码的queue包下有:
RoundQueue(线程不安全),ConcurrentTreeMap(线程安全-put 方法使用了lock 加锁,且 lock = new ReentrantLock(true);)
可重入锁的意思是 对于同一线程可以重复去获取锁。应用场景--递归,例如文件夹遍历目录下的所有文件名。
★ 2、和synchronized 的使用区别/ 说说lock 和 synchronized 锁的区别
synchronized 是一个
关键字
,使用C++实现的,没办法控制锁的开始、锁结束,也没办法中断线程的执行而 lock 是
java层面的实现
,可以获取锁的状态,开启锁,释放锁,通过设置可以中断线程的执行,更加灵活是否自动是否锁:synchronized 会自动是否锁,而 lock 需要手动调用unlock 方法释放,否则会死循环
lock.lock();//其他没有拿到锁的线程?阻塞 卡着不动
boolean res = lock.tryLock(1000, TimeUnit.MILLISECONDS);//一秒之后如果没有拿到锁,就返回false
lock.lockInterruptibly();//中断方法
★ 3、讲讲 trylock、lock方法
lock 锁设计上的核心成员:锁状态、锁拥有者、等待队列
源码方面:在 ReentrantLock 中 使用了关键成员是同步器AQS(源码中的Sync)
trylock方法:获取锁/是否锁成功
锁的状态,0 代表未占用锁,大于0 则代表占用锁的次数。
首先当前线程以CAS的方式,尝试将锁的状态从0修改成1,就是尝试获取锁。
获取到了就把当前线程设置给AQS的属性exclusiveOwnerThread,也就是指明当前锁的拥有者是当前线程。
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {//如果占用锁的是当前线程,则代表重入次数
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
lock方法:加锁
非公平锁模式,首先当前线程以CAS的方式,尝试将锁的状态从0修改成1,就是尝试获取锁。
获取到了就把当前线程设置给AQS的属性exclusiveOwnerThread,也就是指明当前锁的拥有者是当前线程。
当前锁已经被占用,线程会进入等待队列,不断地抢锁,抢到锁直接从等待队列弹出,否则判断线程的状态是否需要挂起(阻塞),这里循环抢锁,不断调用了尝试获取锁的方法,也利用了CAS思想。
// 非公平锁模式 lock = new ReentrantLock();
final void lock() {
// 首先以 CAS 的方式,尝试将state 从0修改成1
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
// compareAndSetState(0, 1)--> CAS 机制
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
// acquire(1);--> CAS 机制
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))//进入等待队列,继续不断尝试获取锁,直到抢到锁则弹出队列,否则判断线程的状态是否需要挂起
selfInterrupt();
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())//判断线程的状态是否需要挂起
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
如果本文对你有帮助的话记得给一乐点个赞哦,感谢!
Lock 锁底层实现的更多相关文章
- 一文带你看懂Java中的Lock锁底层AQS到底是如何实现的
前言 相信大家对Java中的Lock锁应该不会陌生,比如ReentrantLock,锁主要是用来解决解决多线程运行访问共享资源时的线程安全问题.那你是不是很好奇,这些Lock锁api是如何实现的呢?本 ...
- 为什么Java有了synchronized之后还造了Lock锁这个轮子?
众所周知,synchronized和Lock锁是java并发变成中两大利器,可以用来解决线程安全的问题.但是为什么Java有了synchronized之后还是提供了Lock接口这个api,难道仅仅只是 ...
- (删)Java线程同步实现二:Lock锁和Condition
在上篇文章(3.Java多线程总结系列:Java的线程同步实现)中,我们介绍了用synchronized关键字实现线程同步.但在Java中还有一种方式可以实现线程同步,那就是Lock锁. 一.同步锁 ...
- 转: 【Java并发编程】之二十:并发新特性—Lock锁和条件变量(含代码)
简单使用Lock锁 Java5中引入了新的锁机制--Java.util.concurrent.locks中的显式的互斥锁:Lock接口,它提供了比synchronized更加广泛的锁定操作.Lock接 ...
- java并发编程的艺术——第五章总结(Lock锁与队列同步器)
Lock锁 锁是用来控制多个线程访问共享资源的方式. 一般来说一个锁可以防止多个线程同时访问共享资源(但有些锁可以允许多个线程访问共享资源,如读写锁). 在Lock接口出现前,java使用synchr ...
- 多线程系列之自己实现一个 lock 锁
我们面试中经常会被问到多线程相关知识,这一块内容往浅了说大家都会,但是一问到底层实现原理,我们往往就一脸懵逼. 这段时间准备好好学习多线程,接下来会写一系列关于多线程的知识. 我们首先要了解线程,百度 ...
- 【Java并发编程】:并发新特性—Lock锁和条件变量
简单使用Lock锁 Java5中引入了新的锁机制——Java.util.concurrent.locks中的显式的互斥锁:Lock接口,它提供了比synchronized更加广泛的锁定操作.Lock接 ...
- 我是如何一步步的在并行编程中将lock锁次数降到最低实现无锁编程
在并行编程中,经常会遇到多线程间操作共享集合的问题,很多时候大家都很难逃避这个问题做到一种无锁编程状态,你也知道一旦给共享集合套上lock之后,并发和伸缩能力往往会造成很大影响,这篇就来谈谈如何尽可能 ...
- 第44天学习打卡(JUC 线程和进程 并发和并行 Lock锁 生产者和消费者问题 如何判断锁(8锁问题) 集合类不安全)
什么是JUC 1.java.util工具包 包 分类 业务:普通的线程代码 Thread Runnable 没有返回值.效率相比Callable相对较低 2.线程和进程 进程:一个程序.QQ.exe, ...
随机推荐
- Webpack干货系列 | 怎么运用 Webpack 5 处理css/scss/sass、less、stylus样式资源
程序员优雅哥简介:十年程序员,呆过央企外企私企,做过前端后端架构.分享vue.Java等前后端技术和架构. 本文摘要:主要讲解webpack 5 如何高效处理CSS 资源.scss/sass 资源.l ...
- 市面上的工业ERP系统如何区别?存在什么样的不同?
工业发展当中所要涉及到的管理是繁琐而复杂的,在ERP系统的拓展开发中,市面上出现了很多的工业ERP系统来让企业选择.这是近年来非常受欢迎的一种管理手段,依靠计算机系统的强大功能,来实现数据化的管理,企 ...
- mybatis-plus时间字段自动填充
时间代码自动填充的2种方式 数据库方式 将数据库字段create_time和update_time设置CURRENT_TIMESTAMP,create_time字段后面不需要勾选更新,update_t ...
- CentOS删除桌面环境
公司有几台虚拟机安装的是CentOS7的桌面环境,平时也是用终端访问,于是在服务器卡住需要重启时,顺便就把桌面环境给卸载了:测试了好多方法均不成功,最终找到了可行的方式,以此记录: [root@yun ...
- DTS搭载全新自研内核,突破两地三中心架构的关键技术|腾讯云数据库
随着企业规模的扩大,对数据库可用性要求越来越高,更多企业采用两地三中心.异地多活的架构,以提高数据库的异常事件应对能力. 在数据库领域,我们常听的"两地三中心"."异地多 ...
- Collection集合和Collection的常用功能
boolean add(E e); 向集合里添加元素 boolean remove(E e); 删除集合中的某个元素 void clear(); 清空集合的所有元素 boolean contains( ...
- 中高级Java程序员,挑战20k+,知识点汇总(一),Java修饰符
1 前言 工作久了就会发现,基础知识忘得差不多了.为了复习下基础的知识,同时为以后找工作做准备,这里简单总结一些常见的可能会被问到的问题. 2 自我介绍 自己根据实际情况发挥就行 3 Java SE ...
- 神工鬼斧惟肖惟妙,M1 mac系统深度学习框架Pytorch的二次元动漫动画风格迁移滤镜AnimeGANv2+Ffmpeg(图片+视频)快速实践
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_201 前段时间,业界鼎鼎有名的动漫风格转化滤镜库AnimeGAN发布了最新的v2版本,一时间街谈巷议,风头无两.提起二次元,目前国 ...
- ASP.NET Core 6框架揭秘实例演示[31]:路由“高阶”用法
ASP.NET的路由是通过EndpointRoutingMiddleware和EndpointMiddleware这两个中间件协作完成的,它们在ASP.NET平台上具有举足轻重的地位,MVC和gRPC ...
- PostgreSQL定时备份
# PostgreSQL定时备份 # 版本:PostgreSQL14.0 # 一.如果你在pg_hba.conf中设定了密码登录,那么你就需要设置一个默认密码共psql登录的时候跳过验证.如果是roo ...