synchronized 与 volatile

volatile

       可见性:一个线程对共享变量的修改,能够及时的被其他线程看到

  所有的变量都储存在主内存中,每个线程独有自己独立的工作内存(cpu高速缓存部分),线程间不可直接通信,通过主内存进行间接通信,工作内存和主线程间通过bus总线进行通信。volatile底层实现主要是通过汇编lock前缀指令,它会锁定这块内存区域的缓存并回写到主内存,此操作被称为“缓存锁定”,MESI缓存一致性协议机制(store 加锁 write后释放锁)会阻止同时修改被两个以上处理器缓存的内存区域数据。一个处理器的缓存值通过总线回写到内存会导致其他处理器相应的缓存失效。继而操作该变量时需要重新从主内存中读取变量 。(需要注意reference类型,它引用的对象在堆中可被多个线程共享但是reference本身在java栈的局部变量表中,它是线程私有的)

线程对共享变量的操作都必须在自己的工作内存中进行不能直接在主内存中读写。不同线程中的变量值需要通过主内存传递。

  原子性:不确保原子性,如5个线程,每个线程对count++执行10次,最终count结果小于等于50。因为存在线程A,线程B读取count值为10时,都进行++,然后线程A刷新主内存,线程B监控到总线上该变量的值发生改变,使得线程B中count失效重新从主内存中获取count然后线程B刷新主内存(相当于之前的++操作丢掉了)。

Synchronized:可以实现原子性(同步)、可见性。线程解锁前必须把共享变量的最新值刷新到主内存中。加锁时会清空工作内存中共享变量的值,从而使用共享变量时会重新从主内存中读取最新变量值(加锁解锁需要是同一把锁)。

synchronized关键字保证了临界区内变量的可见性和原子性,但无法保证临界区之外访问的变量的原子性。如果对单例对象的读写完全在临界区内,那么就不会出现线程安全问题。不过,这样就带来了性能问题。

Happens-Before规则

Happen-Before规则用来描述两个操作之间的顺序关系,这两个操作可以再一个线程内,也可以不再一个线程内。此顺序并不严格意味着执行时间上的顺序,而是至前一个操作的结果要对后一个操作可见。

另:附上单例模式双重校验相关代码(添加volatile避免指令重排,因为singleInstance存在堆中,虽然A B线程中分别有各自的引用副本但指向的是同一个对象地址)

public class SingleInstance {

    private static volatile SingleInstance singleInstance = null;

    private SingleInstance() {

    }

    public SingleInstance getInstance() {

        if (singleInstance == null) { //A

            synchronized (SingleInstance.class) {

                if (singleInstance == null) {

                    singleInstance = new SingleInstance(); //B

                }

            }

        }

        return singleInstance;

    }

}

重排序:代码书写顺序与实际执行顺序不一致 是编译器或者处理器为提高程序执行性能而做的优化

共享变量线程间不可见原因:重排序、线程交叉执行、共享变量值更新后没有在工作内存和主内存间及时更新

 Synchronized 加到方法上时默认使用当前对象锁。方法一旦执行,就会独占该锁,一直到从该方法返回时或者出现异常时 jvm才将锁释放,此后被阻塞的线程方能获得该锁,从而重新进入可执行状态。

 

 

 

运行结果多运行几次会发现 如果不加synchronized 多个线程会存在交叉运行如:002、022或者线程的先后顺序会变化如002、222。 加了synchronized后虽然线程的先后顺序会变化但会一直到从该方法返回。
Volitale:可见性通过加入内存屏障(确保屏障之前的指令操作都已完成)和禁止指令重排序 在执行写操作时会在写操作后加入一条store屏障指令强制刷新主内存,读操作时会在读操作前加入一条load屏障指令使缓存中的变量值失效 这样每次读取变量值都需要从主内存中读取 不保证原子性 如num++ 循环100 最后的值可能会小于100 修饰共享变量时可保证单线程的原子性。

原文地址:https://www.cnblogs.com/leifonlyone/p/12355464.html