synchronized和lock

Synchronized 

同步代码块

  使用 monitorenter 和 moniterexit 指令实现, monitorenter指令插入到同步代码块的开始位置, moniterexit 指令插入到同步代码块的结束位置, jvm 需要保证每一个 monitorenter 都有一个 moniterexit 与之对应。

  任何对象都有一个 monitor 与之相关联,当且一个 monitor 被持有之后,他将处于锁定状态。

  线程执行到 monitor 指令前,将会尝试获取对象所对应的 monitor 所有权,即尝试获取对象的锁。 

同步方法

  依靠的是方法修饰符上的 ACC_SYNCHRONIZED 实现。 

  Synchronized 方法则会被翻译为普通的方法调用和返回指令,比如 invokevirtual 指令,在 jvm 字节码层面并没有任何特别的指令来实现synchronized 修饰的方法,而是在 class 文件的方法表中将该方法的 access_flags 字段中的synchronized 标志位置为 1,表示该方法为 synchronized 方法,且使用调用该方法的对象 or该方法所属的 class 在 jvm 内部对象表示作为锁对象。 

扫描二维码关注公众号,回复: 1403023 查看本文章

synchronized和lock的区别

  Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

  synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

  Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

  通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

  Lock可以提高多个线程进行读操作的效率。(读写锁)





锁优化:

  自旋锁与自适应自旋:线程挂起和恢复的操作都需要转入内核态中完成,这些操作给系统的并发性能带来了很大的压力,在许多应用中,共享数据的锁定状态只会持续很短的一段时间,为了这段时间去挂起和恢复线程并不值得,可以让后请求锁的线程等待一会儿,但不放弃处理器的执行时间,让线程执行一个忙循环(自旋)。
        自旋锁默认的自旋次数值是10次,可以使用参数-XX:PreBlockSpin更改。
        自适应自旋意味着自旋的时间不再固定,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。
        锁消除:虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除。锁消除的主要判定依据来源于逃逸分析的数据支持。
        锁粗化:如果虚拟机探测到有一系列连续操作都对同一个对象反复加锁和解锁,将会把加锁同步的范围扩展(粗化)到整个操作序列的外部。
        轻量级锁:使用对象头的Mark Word中锁标志位代替操作系统互斥量实现的锁。轻量级锁并不是用来代替重量级锁,它的本意是在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。
        轻量级锁是在无竞争的情况下使用CAS(Compare-and-Swap)操作去消除同步使用的互斥量。
        偏向锁:和轻量级锁原理基本一致,但偏向锁在无竞争的情况下把整个同步都消除掉,连CAS操作都不做了。

猜你喜欢

转载自www.cnblogs.com/mengchunchen/p/9125483.html