乐趣区

关于java:我所知道并发编程之synchronized保证线程安全的原理理论JVM

前言


在上一篇文章中咱们讲到实现了一个数值序列生成器

然而在咱们的多线程的环境下,会发现生成的数值序列不是咱们所预期的那种递增的序列,而是会呈现那种咱们所不预期的谬误

过后的解决方案比较简单,就在那个办法上加了一个 synchronized,于是这个问题就解决了,咱们并没有去具体的解释为什么在办法上加了一个 synchronized 就可能解决

从本篇文章开始,咱们来正式的理解解决线程安全性问题的各种的计划,首先第一个就是 synchronized,咱们前面还会学习其余的锁呀、包含咱们的元子类等等

一、内置锁


在看 synchronized 之前,咱们首先来看 内置锁,什么是内置锁呢

就是说 Java 中每一个对象都能够用作同步的锁,那么这些锁就被称之为内置锁

咱们应用代码领会领会内置锁是什么意思?

public class Sequence {

    int value;

    public synchronized  int getNext(){return  value++;}
    
}

咱们说每一个 Java 中的对象都是一个内置锁,当这个线程在进入同步代码块之前,都必须先取得锁也就是取得内置锁,而后取得锁之后就能够进入到同步代码块中执行

而咱们的 synchronized 放在办法上,也就是说实例办法一般办法上,那么内置锁也就是所谓的对象锁,就是以后类的实例

public class Sequence {


    /**
     * synchronized 放在一般办法上,默认内置锁是以后实例
     * @return
     */
    public synchronized  int getNext(){return  value++;}
    
}

而其余的线程再想进来,那么就必须期待,于是这个线程开始往下执行,咱们之前也都翻译过了,value++ 是执行了好多的字节码指令,那么,等字节码指令执行结束之后,这个线程就能够开释掉锁了,把它拿到的锁开释掉

这个 synchronized 它除了能用在办法上以外,它还能用润饰静态方法,也就是类的办法

public class Sequence {


    private static int value;

    /**
     * synchronized 放在静态方法上,内置锁是以后的 Class 字节码对象
     * @return
     */
    public static synchronized int getPrevious(){return value --;}
    
}

同时它除了润饰办法以外它还可能润饰代码块,咱们能够举个例子应用同步代码块来润饰它

public class Sequence {public int getValue(){synchronized (Integer.valueOf(value)){ }
        if(value>0){return value;}else{return  -1;}
    }
}

万物皆对象,你只有这里指定一个对象,那么,就能够作为一把锁

其实 synchronized 的原理其实就是加了锁,内置锁和互斥锁所决定的。每个对象都有锁,而这些锁都是互斥的,一个进来之后,另外的就不能进来了,因而就能够保障线程的安全性

二、字节码查看 synchronized


那么在 从字节码层面 ,在 Java 虚拟机标准中,能够看到,synchronized 在 Java 虚拟机中执行同步代码块的时候,其实它是基于进入和退出monitor 对象 来实现办法同步的

咱们能够观看字节码指令查看该 Sequence.class 的同步代码块局部

发现在第 4 行就是 monitorenter 进入执行,执行到第 17 行就退出

而当咱们个别编写 if-else 时就会遇到 goto,同时会跳到相应的操作并也开释锁

参考资料


龙果学院:并发编程原理与实战(叶子猿老师)

退出移动版