Java内存模型的三大特性
Java内存模型有三大特性:原子性,可见性,有序性。
1. 原子性:表示该操作不可再分。例如简单的a++操作,这不是一个原子性操作。因为内部是a=a+1,再返回原来的a,这是一个可以分割的操作。在多线程中,非原子性操作会带来线程安全问题。这要我们使用同步技术,变成一个原子性操作。Java提供的原子操作类有AtomInteger,AtomicReference等。
2. 可见性:表示一个线程对变量的修改对其他线程是可见的。Java中可以使用volatile,final,synchronized关键字来保证可见性。
3. 有序性:表示对某一块代码的执行是有序的,串行的进行。Java可以使用volatile和synchronized来保证有序性。volatile保证了可见性,防止指令重排;synchronized保证了原子性,一个代码块只能有一个线程执行。这样保证了持有同一个对象锁的两个同步块只能串行执行。
volatile
volatile关键字可以保证一个线程对变量的修改对其他线程是可见的。这是Java提供的一个弱同步机制。在Java里,一般来说,编译器都会对代码进行指令重排,达到优化的效果。但是这样会导致指令的执行顺序不一定会按照代码编写的顺序进行。使用volatile关键字后,这表示对编译器说不用对该变量进行指令重排,不用对它进行缓存。也因为不能指令重排,对该变量进行写操作时,会加上一些内存屏蔽的指令,这样会导致写操作稍慢。
对于非volatile修饰的变量,一般来说,CPU从内存读取后都会拷贝一份在CPU寄存器中。这样在多线程里,不同的CPU操作不同的线程,就会在不同的CPU的寄存器上放一份,这样会导致数据不一致。使用volatile修饰后,这样可以保证CPU每次都会从内存中刷新读取,而不会缓存到CPU寄存器中。线程对其的修改,会马上回写到内存中。
所以volatile特性为:保证了变量对所有线程可见,禁止指令重排。