咱们日常在看开源项目的源码时,常常可以看到某些类变量定义为volatile,可是每每在本身编程的时候,却又不多用到,那在这篇小短文中,我会跟你们解释如何正确的使用volatile关键字。
在Java中,每个线程有独立的工做内存区域。Java对象的变量值就保存在这些独立的工做内存区域里。因为线程的工做内存是独立于主内存的,这就涉及到JVM须要将变量从主内存拷贝到线程工做内存,若是线程对变量进行了写操做,JVM并无保证什么时候将工做内存的变量值同步到主内存,这样就存在着变量值不一样步的风险。Java的volatile关键字就是用来将类变量定义为多线程只在主内存中对变量进行读写操做。编程
Java的volatile关键字旨在解决变量可见性问题。经过声明计数器变量volatile,全部写入计数器变量将当即写入主存。此外,计数器变量的全部读取都将直接从主存储器读取。多线程
public class VolatileExample { private volatile int count = 0; public void increament() { count++; } public int getCount() { return count; } }
如上面代码所示,将变量声明为volatile能够保证对该变量的其余写入线程的可见性。在上面给出的方案中,一个线程(线程1)修改了计数器,而另外一个线程(线程2)读取了计数器(但从未修改过),声明计数器变量为volatile足以确保线程2写入计数器变量的可见性。
可是,若是线程1和线程2都在增长计数器变量,那么仅声明计数器变量为volatile是不够的,程序依然会有并发冲突的风险。咱们能够经过使用Java提供的原子数据类型(例如AtomicInt或AtomicLong)来避免并发冲突。并发
对于全部多线程应用程序,咱们须要确保几个规则以实现一致的行为:性能
虽然同步方法和代码块能够实现上述两个规则,可是是以牺牲程序性能为代价的。因此volatile是在有些多线程的场景下很是有用的方式,能够帮助确保数据更改的可见性,可是又不须要用到性能开销较大的同步锁(synchronized)。线程