1.volatile的应用
在java多线程并发编程中,synchronized和volatile都扮演中十分重要的角色。volatile能够保证共享变量的可见性,即当一个线程修改了一个共享变量时,另一个线程能够立即得到这个修改后的值。正确使用volatile修饰符,比synchronized的成本更低,因为volatile不会引起线程上下文的切换和调度。
如果一个变量被声明为volatile,java线程内存模型确保所有线程看到这个变量的值都是一致的。
volatile只保证可见性,不保证原子性。即每次读取volatile变量时,都会从共享内存中读取,而不是从缓存读取;每次对volatile变量的写,都会将其直接写入共享内存,并使得其他线程中的引用地址失效,迫使其他线程在读时从共享内存读。
但是对于volatile变量的修改,无法保证其原子性,即
2.volatile的实现原理
volatile能够保证可见性,即一个线程修改了共享变量,其他其他线程能够立即读取到该线程修改后的值,所有线程看到变量的值都是一致的。
对于一个volatile修饰的变量,在对应的汇编代码中,会在指令前面加上一个lock前缀。在一个线程对该变量进行写操作时,CPU会进行一下操作:
- 将当前处理器缓存行的数据写回到系统内存中;
- 将数据写回内存的操作会使得其他CPU里缓存的该内存的地址无效。
现在计算机大多数是多处理器的,为了提高处理速度,处理器不直接和内存进行通信,而是现将系统内存数据得到缓存中,处理器对缓存进行读写,在操作完之后也不确实什么时候能够将缓存中的数据刷新到内存中。就算刷新到缓存中,其他处理器也不一定马上更新自己缓存中的数据,所以这就造成了缓存不一致性。
对于volatile修饰的变量,能够保证一下两个原则:
- lock前缀指令会引起处理器缓存在被修改后立即写到内存中;
- 在一个处理器的缓存写回到内存会使其他处理器的缓存无效。