synchronized和lock

synchronized和lock区别

区别类型

synchronized

Lock

存在层次

Java的关键字,在jvm层面上

是JVM的一个接口

锁的获取

假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待

情况而定,Lock有多个锁获取的方式,大致就是可以尝试获得锁,线程可以不用一直等待(可以通过tryLock判断有没有锁)

锁的释放

1、获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放

在finally中必须释放锁,不然容易造成线程死锁

锁类型

锁可重入、不可中断、非公平

可重入、可判断 可公平(两者皆可)

性能

少量同步

适用于大量同步

支持锁的场景

1. 独占锁

1. 公平锁与非公平锁

synchronized的 加锁流程

  1. 由于HotSpot的作者经过研究发现,大多数情况下,锁不仅不存在多线程竞争,而且总是由同
    一线程多次获得,为了让线程获得锁的代价更低从而引入偏向锁。偏向锁降低了锁重入的代价。偏向锁在获取资源的时候会在锁对象头上记录当前线程ID,偏向锁并不会主动释放,这样每次偏向锁进入的时候都会判
    断锁对象头中线程ID是否为自己,如果是当前线程重入,直接进入同步操作,不需要额外的
    操作。默认在开启偏向锁和轻量锁的情况下,当线程进来时,首先会加上偏向锁,其实这里只
    是用一个状态来控制,会记录加锁的线程,如果是线程重入,则不会进行锁升级。
  2. 获取偏向锁流程:
  1. 判断是否为可偏向状态--MarkWord中锁标志是否为‘01’,是否偏向锁是否为‘1’
    1. 如果是可偏向状态,则查看线程ID是否为当前线程,如果是,则进入步骤 'V',否则进入
      步骤‘c’
  1. 通过CAS操作竞争锁,如果竞争成功,则将MarkWord中线程ID设置为当前线程ID,然
    1. 后执行‘e’;竞争失败,则执行‘d’
    2. CAS获取偏向锁失败表示有竞争。当达到safepoint时获得偏向锁的线程被挂起,偏向锁
      升级为轻量级锁,然后被阻塞在安全点的线程继续往下执行同步代码块
  1. 执行同步代码
  2. 轻量级锁是相对于重量级锁需要阻塞/唤醒涉及上下文切换而言,主要针对多个线程在不同时
    间请求同一把锁的场景。轻量级锁获取过程:
  3. 进行加锁操作时,jvm会判断是否已经是重量级锁,如果不是,则会在当前线程栈帧中划
    1. 出一块空间,作为该锁的锁记录,并且将锁对象MarkWord复制到该锁记录中
    2. 复制成功之后,jvm使用CAS操作将对象头MarkWord更新为指向锁记录的指针,并将锁
      记录里的owner指针指向对象头的MarkWord。如果成功,则执行‘c’,否则执行‘d’
  1. 更新成功,则当前线程持有该对象锁,并且对象MarkWord锁标志设置为‘00’,即表示此
    1. 对象处于轻量级锁状态
    2. 更新失败,jvm先检查对象MarkWord是否指向当前线程栈帧中的锁记录,如果是则执
      行‘e’,否则执行‘f’
  1. 表示锁重入;然后当前线程栈帧中增加一个锁记录第一部分(Displaced Mark Word) 为null,并指向Mark Word的锁对象,起到一个重入计数器的作用
    1. 表示该锁对象已经被其他线程抢占,则进行自旋等待(默认10次),等待次数达到阈值
      仍未获取到锁,则升级为重量级锁
  1. 当有多个锁竞争轻量级锁则会升级为重量级锁,重量级锁正常会进入一个cxq的队列,在调用
    wait方法之后,则会进入一个waitSet的队列park等待,而当调用notify方法唤醒之后,则有
    可能进入EntryList。重量级锁加锁过程:
  1. 分配一个ObjectMonitor对象,把Mark Word锁标志置为‘10’,然后Mark Word存储指向ObjectMonitor对象的指针。ObjectMonitor对象有两个队列和一个指针,每个需要获取锁的线程都包装成ObjectWaiter对象
  2. 多个线程同时执行同一段同步代码时,ObjectWaiter先进入EntryList队列,当某个线程
    1. 获取到对象的monitor以后进入Owner区域,并把monitor中的owner变量设置为当前线
      程同时monitor中的计数器count+1;

为什么synchronized实现锁升级之后为什么提高了效率

synchronized锁升级的流程:无锁->偏向锁->轻量级锁->重量级锁

无锁的性能最高,不做赘述。

偏向锁:只需要走一次对象头上的markword判断,没有CAS,没有自旋,没有阻塞(线程阻塞会从用户态切换到

内核态)

轻量级锁:当偏向锁发送了CAS而没有申请到锁后,升级为轻量级锁。轻量级锁没有自旋,没有阻塞

重量级锁:当轻量级锁自旋后没有申请到锁后会升级为重量级锁。线程向cpu申请锁资源,没有升级到的线

程会阻塞并进入等待队列,会发生频繁的状态切换。

总结:偏向锁是为了避免CAS,在对象头上就把加锁问题解决。轻量级锁和自旋锁是为了避免线程进入内核的阻塞状态,这对性能非常不利;重量级锁是终极方案,避免自旋锁的空耗cpu而没有产生实际工作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值