`

Java 理论与实践: 正确使用 Volatile 变量

 
阅读更多

 

Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是synchronized 的一部分。本文介绍了几种有效使用 volatile 变量的模式,并强调了几种不适合使用 volatile 变量的情形。

锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。

Volatile 变量

Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器、互斥锁或任何具有与多个变量相关的不变式(Invariants)的类(例如 “start <=end”)。

出于简易性或可伸缩性的考虑,您可能倾向于使用 volatile 变量而不是锁。当使用 volatile 变量而非锁时,某些习惯用法(idiom)更加易于编码和阅读。此外,volatile 变量不会像锁那样造成线程阻塞,因此也很少造成可伸缩性问题。在某些情况下,如果读操作远远大于写操作,volatile 变量还可以提供优于锁的性能优势。

正确使用 volatile 变量的条件

您只能在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:

  • 对变量的写操作不依赖于当前值。
  • 该变量没有包含在具有其他变量的不变式中。

实际上,这些条件表明,可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态。

第一个条件的限制使 volatile 变量不能用作线程安全计数器。虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。实现正确的操作需要使 x 的值在操作期间保持不变,而 volatile 变量无法实现这点。(然而,如果将值调整为只从单个线程写入,那么可以忽略第一个条件。)

大多数编程情形都会与这两个条件的其中之一冲突,使得 volatile 变量不能像 synchronized 那样普遍适用于实现线程安全。清单 1 显示了一个非线程安全的数值范围类。它包含了一个不变式 —— 下界总是小于或等于上界。

……

 

见原文: http://www.ibm.com/developerworks/cn/java/j-jtp06197.html

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    Java 理论与实践: 正确使用 volatile 变量 线程同步

    Java语言规范中指出:为了获得佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。  这样当多个线程同时与某个对象交互时,必须要注意到要让线程...

    java入门教程:数据类型_Java理论与实践如何正确使用Volatile变量.docx

    ### Java入门教程:数据类型与正确使用Volatile变量 #### 概述 在Java编程语言中,`volatile`关键字提供了一种轻量级的同步机制,用于确保共享变量的可见性和一定程度上的线程安全性。相比于传统的锁机制如`...

    详解java如何正确使用volatile

    这使得volatile变量在多线程环境下具有了一定程度的线程安全性。 然而,值得注意的是,`volatile`并不保证原子性。这意味着如果一个操作包含多个步骤(如`t++`操作),即使这个操作涉及的变量是volatile的,也不能...

    Java理论与实践:修复Java内存模型1

    新的JMM规定,volatile变量的写操作会强制刷新到主内存,确保其他线程可以立即看到变化。同时,读操作会从主内存获取最新值,而不是从处理器缓存中读取,这样增强了volatile的同步效果。对于final字段,JMM现在保证...

    Java理论与实践:修复Java内存模型2

    同时,volatile读写操作不再允许与非volatile变量的读写进行乱序重排,增强了内存操作的有序性,使得代码的行为更符合开发者的直觉。 此外,JSR 133还强化了final关键字的语义。在并发编程中,不变对象(immutable ...

    Java理论与实践:修复Java内存模型,第1部分

    ### Java理论与实践:修复Java内存模型,第1部分 #### 概述 活跃了将近三年的JSR133近期发布了一项关于如何修复Java内存模型(Java Memory Model, JMM)的重要建议。原始JMM中存在一些严重的缺陷,这导致了原本被...

    concurrent 多线程 教材

    j-concurrent 00 IBM developerWorks 中国 : Java 多线程与并发编程专题 02 Java 程序中的多线程 03 编写多线程的 Java 应用程序 ...37 Java 理论与实践 正确使用 Volatile 变量.mht 38 使用泛型和并发改善集合.mht

    Java并发编程实践

    10. **原子变量与原子类**:`java.util.concurrent.atomic`包提供了原子变量,如`AtomicInteger`、`AtomicLong`,它们支持无锁更新,适用于高并发环境。 11. **死锁、活锁与饥饿**:并发编程中的三大难题,死锁是指...

    Java并发编程实践(Java Concurrency in Practice) (中英版)

    2. **同步机制**:详细阐述了Java中的同步工具,如synchronized关键字、volatile变量、java.util.concurrent包下的锁、条件变量和原子变量类。这部分还深入解析了死锁、活锁和饥饿现象,以及如何避免它们。 3. **...

    JAVA并发编程实践 中文 高清 带书签 完整版 Doug Lea .pdf

    根据提供的文件信息,“JAVA并发编程实践 中文 高清 带书签 完整版 Doug Lea .pdf”,我们可以推断出这份文档主要聚焦于Java并发编程的技术实践与理论探讨。下面将从多个角度来解析这个文档可能涵盖的关键知识点。 ...

    Java并发编程实践 高清扫描版

    总的来说,《Java并发编程实践》涵盖了Java并发编程的各个方面,从基础到高级,从理论到实践,是提升Java并发编程能力的必备读物。通过学习这本书,开发者可以更好地应对并发挑战,编写出高效、可靠的多线程程序。

    JAVA并发编程实践

    2. **同步机制**:Java提供了多种同步机制,如synchronized关键字、volatile变量、java.util.concurrent包下的工具类(如Semaphore、Lock等)。这些机制可以帮助开发者确保共享资源的安全访问,防止数据不一致性和竞...

    JAVA并发编程实践 EN(全)

    2. **线程安全**:讨论线程不安全的代码示例,以及如何通过使用synchronized关键字、 volatile变量、final关键字以及ThreadLocal来确保线程安全。此外,还会介绍Java内存模型(JMM)和其对并发编程的影响。 3. **...

    java并发编程实践

    为了保证多线程程序的正确性,Java引入了Happens-before规则,这是一系列有序性的保障,其中包含程序顺序规则、监视器锁规则、volatile变量规则以及传递性规则等。 关于锁,Java并发编程实践中提到了synchronized...

    Java并发编程:设计原则与模式(Concurrent.Programming.in.Java)(中英版)

    《Java并发编程:设计原则与模式》是一本深入探讨Java多线程编程的权威书籍,由Doug Lea撰写,第二版全面涵盖了Java并发处理的各个方面。这本书不仅提供了丰富的理论知识,还介绍了实战中的设计原则和模式,对于Java...

    Java试题笔试题目答案.pdf

    - 顺序性:volatile变量的赋值操作不会被编译器优化而与其他语句重排序,保证了操作的有序性。 - 可见性:当一个线程修改了volatile变量,这个修改对其他所有线程都是立即可见的。 - 在某些情况下,volatile还...

    一本经典的多线程书籍 Java并发编程 设计原则与模式 第二版 (英文原版)

    2. **同步机制**:详细解析了Java中的同步工具,如`synchronized`关键字、volatile变量、java.util.concurrent包中的Lock接口及其实现,如ReentrantLock,以及Condition等。同时,还会探讨如何正确地使用这些机制...

    Java并发编程实践--电子书.rar

    Java提供了synchronized关键字和volatile变量来保证可见性和互斥性,确保多个线程在访问共享数据时的正确性。此外,java.util.concurrent包提供了高级并发工具,如Semaphore(信号量)、CyclicBarrier(循环屏障)和...

Global site tag (gtag.js) - Google Analytics