深入理解深入理解Java中的中的volatile关键字(总结篇)关键字(总结篇)
volatile这个关键字,不仅仅在Java语言中有,在很多语言中都有的,而且其用法和语义也都是不尽相同的。这
篇文章主要介绍了Java中的volatile关键字,需要的朋友可以参考下
基本概念基本概念
--------------------------------------------------------------------------------
先补充一下概念:先补充一下概念:Java 内存模型中的可见性、原子性和有序性。内存模型中的可见性、原子性和有序性。
可见性:可见性:
可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉。通常,我们无法确保执行读操作的线程能适时地
看到其他线程写入的值,有时甚至是根本不可能的事情。为了确保多个线程之间对内存写入操作的可见性,必须使用同步机
制。
可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果。另一个线程
马上就能看到。比如:用volatile修饰的变量,就会具有可见性。volatile修饰的变量不允许线程内部缓存和重排序,即直接修
改内存。所以对其他线程是可见的。但是这里需要注意一个问题,volatile只能让被他修饰内容具有可见性,但不能保证它具
有原子性。比如 volatile int a = 0;之后有一个操作 a++;这个变量a具有可见性,但是a++ 依然是一个非原子操作,也就是这
个操作同样存在线程安全问题。
在 Java 中 volatile、synchronized 和 final 实现可见性。
原子性:原子性:
原子是世界上的最小单位,具有不可分割性。比如 a=0;(a非long和double类型) 这个操作是不可分割的,那么我们说
这个操作时原子操作。再比如:a++; 这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。非原子操作都会存
在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作。一个操作是原子操作,那么我们称它具
有原子性。java的concurrent包下提供了一些原子类,我们可以通过阅读API来了解这些原子类的用法。比如:
AtomicInteger、AtomicLong、AtomicReference等。
在 Java 中 synchronized 和在 lock、unlock 中操作保证原子性。
有序性:有序性:
Java 语言提供了 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性,volatile 是因为其本身包含“禁止指
令重排序”的语义,synchronized 是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的,此规则决
定了持有同一个对象锁的两个同步块只能串行执行。
正题正题
在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性、
可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized、volatile、final、concurren包等。在前一
篇文章中,我们也介绍了synchronized的用法及原理。本文,来分析一下另外一个关键字——volatile。
本文就围绕volatile展开,主要介绍volatile的用法、volatile的原理,以及volatile是如何提供可见性和有序性保障的等。
volatile这个关键字,不仅仅在Java语言中有,在很多语言中都有的,而且其用法和语义也都是不尽相同的。尤其在C语言、
C++以及Java中,都有volatile关键字。都可以用来声明变量或者对象。下面简单来介绍一下Java语言中的volatile关键字。
volatile的用法的用法
volatile通常被比喻成"轻量级的synchronized",也是Java并发编程中比较重要的一个关键字。和synchronized不同,volatile是
一个变量修饰符,只能用来修饰变量。无法修饰方法及代码块等。
volatile的用法比较简单,只需要在声明一个可能被多线程同时访问的变量时,使用volatile修饰就可以了。
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}