美文网首页
synchronized

synchronized

作者: Ray昱成 | 来源:发表于2019-01-28 15:36 被阅读0次

    介绍

    synchronized是JVM内建的同步机制,提供了互斥性和可见性来保证多线程安全。当某一线程获取到当前锁时,其他线程只能处于阻塞或者等待状态。

    用法

    可作用于方法上或者代码块中

    • 作用于静态方法时,其他synchronized修饰的静态方法或者synchronized(Class)代码段都会被挂起
    • 作用与动态方法时,该对象的其他synchronized修饰的动态方法或者synchronized(this)代码段都会被挂起

    实现原理

    synchronized代码块是由一对monitorenter/monitorexit实现的,Monitor对象是实现同步的基本单元。
    如下代码:

    public void test(){
         synchronized(this){
              int i=0;
         }
      }
    

    反编译后如下:


    image.png

    Monitor的实现

    之前的Monitor实现主要依靠操作系统内部的互斥锁来实现,需要进行用户态到内核态的转变,所以是一个重量级的操作锁。
    JDK8对此进行了改良,提供了三种实现Monitor的方式,分别为偏斜锁、轻量级锁、重量级锁

    • 偏斜锁(Biased Locking)
      没有锁竞争时,默认使用偏斜锁。利用CAS将对象头上的Mark Word部分设置为当前线程ID,但并不是真正意义上的互斥所。好处是由于大部分对象声明周期只会被一个线程锁定,所以偏斜锁无竞争开销。
    • 轻量级锁
      当出现锁竞争时,也就是另外一个线程试图锁定偏斜锁处理过的对象时,JVM将切换到轻量级锁,利用CAS和Mark Word来试图获取锁,如果重试后扔不成功,则进一步升级为重量级锁。

    读写锁

    独占锁要么不占,要么独占,这种行为有一定的局限性,比如在一个写少读多的并发情况下,并不适合使用独占锁。
    读写锁的原理是读锁时共享,写锁时互斥,运行阶段,如果读锁试图锁定对象,写锁正在被某个线程持有,此时读锁会等待对方操作结束,从而保证数据的正确性。
    读写锁的粒度虽然相对较细,但是却增加了比较大的开销。
    StampedLock是java8提供的更优于读写锁的类。不仅提供了读锁和写锁,还支持优化读模式。基于一种假设:大多数情况下读和写不会发生冲突,其逻辑先试着读,然后通过validate函数确认是否进入了写模式,
    如果没有则可以避免多余的开销;如果进去了,则尝试获取读锁。

    自旋锁

    在无法获取到锁时,采用轮询体内实现,当循环条件被外界改变时,进入临界区

    • 自旋锁在轮询时不会进入阻塞状态,从而避免了线程状态上下文的切换开销
    • 轮询会一直占用CPU,如果轮询时间较长则影响CPU执行其他线程,所以适用于锁竞争不激烈的场景。否则还是使用互斥锁

    相关文章

      网友评论

          本文标题:synchronized

          本文链接:https://www.haomeiwen.com/subject/srdajqtx.html