下面我为你详细讲解必须要学会的JMM与volatile的完整攻略。
JMM介绍
JMM(Java Memory Model)即Java内存模型,用于规范Java程序中线程对共享变量的操作。JMM为Java程序中的线程提供可见性、有序性、原子性等保证,从而提高程序并发性能。
JMM提供的保证
- 可见性: 一个线程修改了共享变量的值,这个值的变化对其他线程是可见的。
- 有序性: Java程序中的所有操作都是有序的,JMM通过禁止某些重排序优化来保证有序性。
- 原子性: 对于某些复合操作,JMM保证这些操作要么全部执行,要么全部不执行。
JMM存在的问题
由于JVM的实现,每个线程都有自己的本地内存,线程之间的共享变量存于主内存中,因此在并发编程中需要考虑多线程之间的内存可见性和顺序性问题。
虽然JMM提供了可见性、顺序性、原子性的保证,但是只能保证某种程度的有序性和可见性,并不能保证所有的交互都按照开发人员预想的方式运行。
volatile关键字介绍
volatile关键字是JMM提供的一种保证内存可见性的手段。定义一个变量为volatile,JVM会避免执行重排序和缓存优化,保证该变量的每次写入都立即同步到主内存中,并且每次读取都从主内存中读取。
需要注意的是,volatile保证的是变量的可见性,保证的是单变量的操作是原子的,但是并不保证多次操作是原子的,因此对于多次操作的复合操作仍需使用锁或Atomic类进行保证。
volatile的用法
在Java中,声明一个变量为volatile需要使用volatile关键字来修饰:
public static volatile int count = 0;
在此例中,修饰的是静态变量count。该声明会告诉JVM将count存储到全局内存中,每个线程都将去电明这个全局变量,而且在修改count时会先更新到全局内存中。
下面是一个使用volatile关键字的示例:
public class VolatileTest {
public static volatile int value = 0;
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
while (value == 0) {
}
System.out.println("Value has changed,value=" + value);
}
}.start();
// main thread paused for 1s to make sure that the new thread already started
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
value = 1;
System.out.println("Value is ready to change,value=" + value);
}
}
在该示例中,启动了一个新线程,并在该线程内部对value进行了轮询,判断value是否被main线程修改,如果修改过则打印修改后的结果。在main线程中,修改了value的值为1,此时新线程会感知到value已经被修改并且会结束轮询并打印修改后的结果。
volatile与JMM的关系
JMM中提供了volatile关键字作为保证可见性的手段。volatile可以在一定程度上解决Java编程中的内存可见性问题。但是需要注意的是,volatile仅能保证单个变量的可见性,如果需要保证复合操作的原子性还需要使用synchronized或者Atomic类。
在Java并发编程中,虽然volatile不能保证一些复合操作的原子性,但是在一些特定的场景下使用volatile仍然是非常有用的,例如状态标志、单例模式等。
以上就是“必须要学会的JMM与volatile”的完整攻略了。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:必须要学会的JMM与volatile - Python技术站