volatile与synchronized详解

文章目录:java

1.简单理解Volatile和synchronized缓存

2.Volatile详解多线程

3.synchronized详解app

4.Volatile与synchronized的区别与联系jvm

 

1.简单理解Volatile和synchronized:优化

synchronized:当被synchronized修饰时,synchronized会锁定当前变量,只有当前线程可以访问该变量,其余线程会被阻塞。spa

volatile:当volatile修饰变量时,编译器对此变量的读写操做不作任何优化,每次都会去内存去读,写也是写到内存,不作任何的缓存优化线程

volatile,final,synchronized均可以实现可见性。code

2.Volatile详解对象

volatile可见性原理

可见性:任何线程能立刻看到它的结果

volatile的本质是告诉jvm这个变量是在寄存器中的值是不肯定的,加入volatile关键字之后,保存数据会同步到主内存中,而另外一端读数据时也会从主内存中读取,volatile使用cpu的缓存锁来保证可见性。

volatile禁止指令重排序

指令重排序的目的: 提升cpu运算效率

cpu提升利用率的过程:进程 -> 线程 -> 指令

指令重排序究竟是什么?

举个栗子:写代码每一行都是一个指令,有的指令运行时间比较长,不能让其余指令排队等着,这时对指令进行从新排序,来提升运行效率

 

无论怎么重排序,单线程都遵循 as-if-serial语义,而多线程遵循 happen-before

讲清楚指令重排序了,volatile如何防止指令重排?

Volatile变量在赋值后会有一个lock add命令,这个命令至关于内存屏障,重排序时不能把屏障后的指令重排序到屏障以前。

volatile使用案例

案例1

在下面这个单例模式下,会指令重排序,若是这时多线程访问,这时尚未初始化对象,会发生不完整实例。 如图2-1

使用volatile修饰 instance 防止这种问题发生

public class VolatileDemo {

    private  volatile static  VolatileDemo instance;

    private VolatileDemo(){}
   
    /*
     * 懒汉模式 double check
     * 不完整实例,指令重排序致使多线程访问发生不完整实例,
     * 解决办法:    private volatile static  VolatileDemo instance;
     * 防止指令重排序
     * */

    public static VolatileDemo getInstance2(){
        if (instance == null ){
            synchronized (VolatileDemo.class){
                if (instance == null){
                    instance = new VolatileDemo();
                }
            }
        }
        return instance;
    }
}

 图2-1

案例2

volatile int i;
public void add{
    i++;
}

这里先要读i值 ,而后++,又同步。 再多线程操做时会出错,原理同案例1,有关指令重排序的问题致使的。

3.synchronized详解

当被synchronized关键字修饰的代码块在被编译成字节码的时候,会在该代码块开始和结束的地方加入 monitorenter 和 moniterexist 指令,任何对象都有一个monitor相关联,当一个monitor被持有后,他就处于锁定状态,当线程执行到monitorenter指令时,会获尝试获取对象对应的monitor的全部权,即获取对象的锁。monitor指令如图3-1

                       图3-1

虚拟机在执行这两个命令的时候,会检查对象的锁状态是否为空或当前线程是否已经拥有对象的锁,

若是是 则对象锁的计数器加 1 ,直接进入同步代码,

若是不是,则当前线程阻塞等待,等待锁释放。

4.Volatile与synchronized的区别与联系

(1)volatile,final,synchronized均可以实现可见性

(2)volatile的本质是告诉jvm这个变量是在寄存器中的值是不肯定的,须要从主存中读取。

(3)synchronized是锁定当前变量,只有当前线程可以访问该变量,其余线程被阻塞。

(4)volatile仅能实现变量的修改可见性,不具有原子性,而synchronized能够实现变量的修改可见性和原子性

(5)volatile标记的变量不会被编译器优化,而synchronized能够(禁止指令重排序)

(6)volatile使用在变量级别,而synchronized可使用在变量和方法

(7)volatile不会阻塞线程,而synchronized可能会

相关文章
相关标签/搜索