JUC学习笔记六:synchronized和ReentrantLock详解

synchronized

synchronized关键字是通过jvm实现的

在jdk1.6之前:简单粗暴的字节码层面实现同步。

  • 如果使用同步代码块,那么就是通过monitorenter和monitorexit指明同步代码块开始和结束的位置,synchronized代码块会维护一个锁计数器,当enter时,先判断计数器是不是0,如果是0就进入,进入之后将计数器加1,在退出时将计数器设为0,表明锁被释放。
  • 如果使用同步方法,那么这个方法的字节码会有一个标识 ACC_SYNCHRONIZED,如果字节码运行的时候遇到这个标识,就会调用同步机制加锁。

在jdk1.6之后:引入了锁升级的过程
1.6之后synchronized的性能有了很大的提升,他并不是上来就加上最重量级的锁。而是有四个状态,根据线程竞争的激烈程度从无锁到重量级锁逐步升级。
这四个状态分别是:无锁–>偏向锁–>轻量级锁–>重量级锁

无锁:就是没有锁
偏向锁:无线程竞争,偏向于先进来的线程,先进来的线程获得偏向锁,如果这个锁没有被其他进来的线程获取,那么持有偏向锁的线程就无需同步。
轻量级锁:就是自旋锁,通过CAS实现
重量级锁:同1.6之前

其他概念:
锁消除:检测到某些数据不可能存在线程竞争,转变为无锁,锁被消除。
锁粗化:原则上,我们在编写代码的时候,总是推荐将同步快的作用范围限制得尽量小——只在共享数据的实际作用域才进行同步,这样是为了使得需要同步的操作数量尽可能变小,如果存在锁竞争,那等待线程也能尽快拿到锁。

ReentrantLock

ReentrantLock可以有两种模式,默认是非公平锁,但是如果构造器传了true, 那么就是公平锁。
实现方式:CAS和AQS双向队列实现

公平锁模式:
调用lock.lock():
先调用AQS的acquire方法,将线程放进队列,然后判断这个进队列的线程前面的结点有没有等待时间更长的线程,如果有,让等待时间最长的线程获得锁,如果没有,那么这个线程获得锁。

非公平锁模式:
调用lock.lock():
不管三七二十一先CAS抢锁,没抢到再去调用acquire()排队,也就是说虽然也有aqs队列,但是不能保证队列头部的线程能获取到锁,因为所有其他线程第一次进来都有获取锁的权力。

为什么叫可重入?
维护一个int state,线程A获得锁,state加1,线程A还可以再获得锁,state再加1,变为2,直到线程A释放两次锁,state变为0时,其他线程才能再去获得锁,线程A可以通过同一把锁重入,这就是可重入锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值