继续之前文章。
无论是HashMap,LinkedHashMap,ArrayList等都是非线程安全的,在并发情况下会出现问题,而Jdk也提供了concurrent包,该包下边主要是关于线程安全相关的类,例如ConcurrentHashMap,ConcurrentHashMap的实现原理不在这里阐述了,这里主要讲解跟它有关的锁问题ReentrantLock(重入锁),CAS(比较与交换)

ReentrantLock

  1. 说明
    分为公平锁和非公平锁两个都继承内部类Sync,各自实现,而构造方法也可以指定实例化时采用公平锁还是非公平锁。
  • 公平锁:会按照请求的顺序获取锁,如果锁已经被占用,则新来的请求放到队列中。
  • 非公平锁:不是按照请求顺序获取锁,存在插队现象。
  1. 类的结构
//内部类
private final Sync sync;
//定义了内部类
abstract static class Sync extends AbstractQueuedSynchronizer
//非公平锁继承内部类
static final class NonfairSync extends Sync
//公平锁继承内部类
static final class FairSync extends Sync
  1. ReentrantLock构造方法有两个:无参和有参(指定采用公平和非公平)
    分别看下是如何初始化的。
public ReentrantLock() {//默认非公平锁sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {//若fair为true,则是公平锁,否则非公平锁sync = fair ? new FairSync() : new NonfairSync();}
  1. 接下来看下公平锁lock()是如何实现加锁的
public void lock() {//根据实例化的锁走对应的子类实现sync.lock();
}
//公平锁
final void lock() {//调用父类AbstractQueuedSynchronizer中的方法acquire(1);}public final void acquire(int arg) {//tryAcquire子类重新了所以调用子类,尝试获取锁,若能获取到直接返回if (!tryAcquire(arg) &&//获取不到则直接加入到等待队列中acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();
}protected final boolean tryAcquire(int acquires) {//获取当前线程final Thread current = Thread.currentThread();//获取状态,获取状态0int c = getState();if (c == 0) {//判断队列中是否有比自己优先级更高的线程,若没有则通过CAS获取锁if (!hasQueuedPredecessors() &&//通过CAS获取锁,具体如何获取后面说compareAndSetState(0, acquires)) {//设置自己持有锁,并返回truesetExclusiveOwnerThread(current);return true;}}//若当前持有锁的线程是自己,则将重入次数累加else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded");//设置新的状态,并返回truesetState(nextc);return true;}return false;
}
//上边代码中的hasQueuedPredecessors
public final boolean hasQueuedPredecessors() {//Node包含下个线程和上个线程,采用这种方式形成一个链表//Node中有等待状态waitStatus,前节点prev,下一个节点next及当前线程thread,//下一个等待线程nextWaiterNode t = tail; // Read fields in reverse initialization orderNode h = head;Node s;//判断是否有等待获取锁的节点return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());
}

公平锁的过程是:
首先尝试获取锁,获取锁的过程中会判断队列中是否有比自己优先级高的线程若有则返回false,加锁失败,若没有则通过CAS获取锁,并设置自己为当前持有锁的线程,返回true;
若是重入则次数加1,并返回true;若获取不到所则将自己加到队列中等待获取锁。
5. 非公平锁,会有插队的现象,导致这中现象是因为每次lock都会先获取锁,不会检查队列中是否包含等待线程,若获取到则插队成功,否则失败添加到队列中。

final void lock() {//采用CAS方式,若获取到则设置自己为所的持有者否则按照公平锁的方式请求。if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}
  1. tryLock() 尝试获取锁,获取到就返回true,否则失败false
public boolean tryLock() {return sync.nonfairTryAcquire(1);
}
//与公平锁有点类似
final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {//与公平锁不同之处,不判断队列,直接通过CAS方式获取锁if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}
  1. tryLock(long timeout, TimeUnit unit)指定等待时间,到时还未获取到锁则返回false。
public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
public final boolean tryAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {//若线程中断则返回异常if (Thread.interrupted())throw new InterruptedException();//tryAcquire尝试获取锁,非公平和公平各自实现,可以看上边代码return tryAcquire(arg) ||doAcquireNanos(arg, nanosTimeout);
}

CAS

在ReentrantLock中核心部分采用的还是CAS(比较与交换,Compare and swap)获取锁,CAS是CPU的指令,意思是“认为val的值是1,如果是1则将val的值更新为2,否则不做更改,并返回V实际的值”。

先介绍到这里有什么不妥之处也请看到的大咖纠正。

也可以关注公众号进行探讨

ReentrantLock与CAS相关推荐

  1. 在竞争激烈的情况下,ReentrantLock与CAS的性能比较

    这次看了源码,发现ReentrantLock的底层实现是AQS,而AQS底层实现是Volatile+CAS+CLH队列,因此想看看ReentrantLock与CAS的性能比较,因此做了这么一组实验. ...

  2. JUC:ReentrantLock互斥锁

    JUC:ReentrantLock 关键词 公平锁和非公平锁:ReentrantLock(CAS+AQS队列) 公平锁和非公平锁的变量 private final Sync sync;(核心) try ...

  3. 一线互联网常见的14个Java面试题,你颤抖了吗程序员

    跳槽不算频繁,但参加过不少面试(电话面试.face to face面试),面过大/小公司.互联网/传统软件公司,面糊过(眼高手低,缺乏实战经验,挂掉),也面过人,所幸未因失败而气馁,在此过程中不断查缺 ...

  4. java锁的有哪些_「并发编程」Java锁分类和特点有哪些

    公平锁.非公平锁:公平锁指多个线程按照申请锁的顺序来获取锁,非公平锁就是没有顺序完全随机,所以能会造成优先级反转或者饥饿现象:synchronized 就是非公平锁,ReentrantLock(使用 ...

  5. RocketMQ Broker的最佳实践

    RocketMQ Broker的最佳实践 翻译自rocket官方文档 Broker Role Broker的方式有异步主,同步主,或者从.如果不能容忍消息丢失,建议以同步主从方式部署.如果对丢失没那么 ...

  6. JAVA后端面试100 QA之第一篇

    转载自  JAVA后端面试100 Q&A之第一篇 1. synchronized和reentrantlock异同 相同点 都实现了多线程同步和内存可见性语义 都是可重入锁 不同点 实现机制不同 ...

  7. java 锁_Java之线程并发的各种锁、锁、锁

    因为两周没更新了... 也不是懒,这两周确实有些忙,赶项目进度赶的不亦乐乎... 终于赶在工期前,可以进入内测了,我也有了些时间,可以更新啦... 线程并发锁是很常见的问题,而且在Java中锁的类型. ...

  8. 最全的BAT大厂面试题整理,系列篇

    前言 看到一篇文章中提到"最近几年国内的初级Android程序员已经很多了,但是中高级的Android技术人才仍然稀缺",这的确不假,从我在百度所进行的一些面试来看,找一个适合的高 ...

  9. 一线互联网常见的14个Java面试题,你颤抖了吗程序员...

    跳槽不算频繁,但参加过不少面试(电话面试.face to face面试),面过大/小公司.互联网/传统软件公司,面糊过(眼高手低,缺乏实战经验,挂掉),也面过人,所幸未因失败而气馁,在此过程中不断查缺 ...

最新文章

  1. Oracle VM VirtualBox启动新建虚拟机弹错--不能为虚拟机xxxx电脑 打开一个新任务 解决方法;
  2. AI发展进入2.0时代!英特尔在落地中总结4大经验、分享7个案例
  3. hbase中为何不能向表中插入数据_Hbase快速入门(超精炼总结)
  4. Python实训day07pm【Selenium操作网页、爬取数据-下载歌曲】
  5. Winform将网页生成图片
  6. windows python安装opencv_OpenCV开发(1)——OpenCV3.4+Python3.5+Windows10安装问题解决
  7. 我有单片机,你有酒吗?
  8. 错误C4996:'std :: _Copy_impl'
  9. 【剑指offer】_17正则表达式的匹配
  10. 地表反射率影响因素_【热岛强度可影响城市夏季降水落区】
  11. android webview 长按复制,Android webview 点击或长按有蒙层 – 热爱改变生活
  12. BZOJ 1786 DP
  13. ubuntu 安装 swoole 和mac 安装swoole 扩展
  14. JDK、JRE、JVM的区别及JavaSE、JavaEE和JavaME的区别?
  15. 堆排序(C++实现,非常简洁明了)
  16. Category为什么会覆盖原来类中的方法?
  17. QCC3040一拖二发射器(aptXLL)replace CSR8670
  18. 2022-2027年中国暖气片行业市场全景评估及发展战略规划报告
  19. 2022年下半年网络工程师下午真题及答案解析
  20. 按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)。Java实现

热门文章

  1. matlab 多能源调度,水电站中长期优化调度的粒子群算法MATLAB源码
  2. 如何自己修电脑(电脑修复大全)
  3. 李阳疯狂英语学习法之句子处理十步骤
  4. 对于侵犯我著作权无良人员的一个汇总
  5. Avrora学习笔记(官网)
  6. UI设计师如何转型产品经理,我给想转型产品都一些建议
  7. 2022-2028年全球与中国刚柔印刷电路板(PCB)行业市场需求预测分析
  8. OpenGL学习笔记一之PBR篇一 理论
  9. 英语口语8000句-在工作单位
  10. 基于基因的生成式设计/艺术,CryptoKitties以太猫研究