volatile(四)

简介: volatile 这个关键字大家都不陌生,这个关键字一般通常用于并发编程中,是 Java 虚拟机提供的轻量化同步机制,你可能知道 volatile 是干啥的,但是你未必能够清晰明了的知道 volatile 的实现机制,以及 volatile 解决了什么问题,这篇文章我就来带大家解析一波。

如何正确的使用 volatile 变量

上面我们聊了这么多 volatile 的原理,下面我们就来谈一谈 volatile 的使用问题。

volatile 通常用来和 synchronized 锁进行比较,虽然它和锁都具有可见性,但是 volatile 不具有原子性,它不是真正意义上具有线程安全性的一种工具。

从程序代码简易性和可伸缩性角度来看,你可能更倾向于使用 volatile 而不是锁,因为 volatile 写起来更方便,并且 volatile 不会像锁那样造成线程阻塞,而且如果程序中的读操作的使用远远大于写操作的话,volatile 相对于锁还更加具有性能优势。

很多并发专家都推荐远离 volatile 变量,因为它们相对于锁更加容易出错,但是如果你谨慎的遵从一些模式,就能够安全的使用 volatile 变量,这里有一个 volatile 使用原则

只有在状态真正独立于程序内其他内容时才能使用 volatile

下面我们通过几段代码来感受一下这条规则的力量。

状态标志

一种最简单使用 volatile 的方式就是将 volatile 作为状态标志来使用。

volatile boolean shutdownRequested;
public void shutdown() { shutdownRequested = true; }
public void doWork() { 
    while (!shutdownRequested) { 
        // do stuff
    }
}

为了能够正确的调用 shutdown() 方法,你需要确保 shutdownRequested 的可见性。这种状态标志的一种特性就是通常只有一种状态转换:shutdownRequested 的标志从 false 转为 true,然后程序停止。这种模式可以相互来回转换。

双重检查锁

使用 volatile 和 synchronized 可以满足双重检查锁的单例模式。

class Singleton{
    private volatile static Singleton instance = null;
    private Singleton() {}
    public static Singleton getInstance() {
        if(instance == null) {
            synchronized (Singleton.class) {
                if(instance == null)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

这里说下为什么要用两次检查,假如有两个线程,线程一在进入到 synchronized 同步代码块之后,在还没有生成 Singleton 对象前发生线程切换,此时线程二判断 instance == null 为 true,会发生线程切换,切换到线程一,然后退出同步代码块,线程切换,线程二进入同步代码块后,会再判断一下 instance 的值,这就是双重检查锁的必要所在。

读-写锁

这也是 volatile 和 synchronized 一起使用的示例,用于实现开销比较低的读-写锁。

public class ReadWriteLockTest {
        private volatile int value;
    public int getValue() { return value; }
    public synchronized int increment() {
        return value++;
    }
}

如果只使用 volatile 是不能安全实现计数器的,但是你能够在读操作中使用 volatile 保证可见性。如果你想要实现一种读写锁的话,必须进行外部加锁。

相关文章
|
6月前
|
缓存 Java 编译器
volatile与synchronized
volatile与synchronized
59 0
|
缓存 Java 编译器
|
Java
浅谈volatile
浅谈volatile
69 0
|
存储 SQL 缓存
|
SQL
volatile的正确使用(七)
volatile的正确使用(七)
106 0
volatile的正确使用(七)
volatile与JMM(二)
问:volatile凭什么可以保证可见性和有序性 答: 内存屏障
100 0
volatile与JMM(二)
|
存储 缓存 人工智能
volatile(三)
volatile 这个关键字大家都不陌生,这个关键字一般通常用于并发编程中,是 Java 虚拟机提供的轻量化同步机制,你可能知道 volatile 是干啥的,但是你未必能够清晰明了的知道 volatile 的实现机制,以及 volatile 解决了什么问题,这篇文章我就来带大家解析一波。
volatile(三)
|
SQL 存储 算法
volatile详解
在单线程环境中,我们几乎用不到这个关键词,但是多线程环境中,这个关键词随处可见。而且也是面试的常客。总的来说,volatile有以下三个特性: 保证可见性; 不保证原子性; 禁止指令重排。 下面就来详细的说说这三个特性。
volatile详解
|
存储 缓存 安全
synchronized&volatile (二)
synchronized&volatile (二)
202 0