`
85977328
  • 浏览: 1898609 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java并发(二十六)正确使用Volatile变量

 
阅读更多
概述
您只能在有限的一些情形下使用 volatile 变量替代锁。要使volatile变量提供理想的线程安全,必须同时满足下面两个条件:
  • 对变量的写操作不依赖于当前值。
  • 该变量没有包含在具有其他变量的不变式中。

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

与锁相比,Volatile 变量是一种非常简单但同时又非常脆弱的同步机制,它在某些情况下将提供优于锁的性能和伸缩性。如果严格遵循 volatile 的使用条件
—— 即变量真正独立于其他变量和自己以前的值
—— 在某些情况下可以使用 volatile 代替 synchronized 来简化代码。
然而,使用 volatile 的代码往往比使用锁的代码更加容易出错。当你在线程中读取一个非volatile变量时,你最终能读取它更新的那个值。

原子访问
在编程过程中,原子操作是指所有操作都同时发生。原子操作不能被中途打断:要么全做,要么不做。原子操作在完成前不会有看得见的副作用。

我们发现像c++这样的增量表达式,并没有描述原子操作。即使是非常简单的表达式也能够定义成能被分解为其他操作的复杂操作。然而,有些操作你可以定义为原子的:

对引用变量和大部分基本类型变量(除long和double之外)的读写是原子的。
对所有声明为volatile的变量(包括long和double变量)的读写是原子的。

原子操作不会交错,于是可以放心使用,不必担心线程干扰。然而,这并不能完全消除原子操作上的同步,因为内存一致性错误仍可能发生。使用volatile变量可以降低内存一致性错误的风险,因为对volatile变量的任意写操作,对于后续在该变量上的读操作建立了happens-before关系。这意味着volatile变量的修改对于其他线程总是可见的。更重要的是,这同时也意味着当一个线程读取一个volatile变量时,它不仅能看到该变量最新的修改,而且也能看到致使该改变发生的代码的副效应。

使用简单的原子变量访问比通过同步代码来访问更高效,但是需要程序员更加谨慎以避免内存一致性错误。至于这额外的付出是否值得,得看应用的大小和复杂度。

java.util.concurrent包中的一些类提供了一些不依赖同步机制的原子方法。

常规用法
模式 #1:状态标志
volatile boolean shutdownRequested;
...
public void shutdown() { shutdownRequested = true; }
public void doWork() { 
    while (!shutdownRequested) { 
        // do stuff
    }
}


模式 #2:一次性安全发布(one-time safe publication)
public class BackgroundFloobleLoader {
    public volatile Flooble theFlooble;

    public void initInBackground() {
        // do lots of stuff
        theFlooble = new Flooble();  // this is the only write to theFlooble
    }
}

public class SomeOtherClass {
    public void doWork() {
        while (true) { 
            // do some stuff...
            // use the Flooble, but only if it is ready
            if (floobleLoader.theFlooble != null) 
                doSomething(floobleLoader.theFlooble);
        }
    }
}


模式 #3:独立观察(independent observation)
public class UserManager {
    public volatile String lastUser;

    public boolean authenticate(String user, String password) {
        boolean valid = passwordIsValid(user, password);
        if (valid) {
            User u = new User();
            activeUsers.add(u);
            lastUser = user;
        }
        return valid;
    }
}


模式 #4:“volatile bean” 模式
@ThreadSafe
public class Person {
    private volatile String firstName;
    private volatile String lastName;
    private volatile int age;

    public String getFirstName() { return firstName; }
    public String getLastName() { return lastName; }
    public int getAge() { return age; }

    public void setFirstName(String firstName) { 
        this.firstName = firstName;
    }

    public void setLastName(String lastName) { 
        this.lastName = lastName;
    }

    public void setAge(int age) { 
        this.age = age;
    }
}


模式 #5:开销较低的读-写锁策略
@ThreadSafe
public class CheesyCounter {
    // Employs the cheap read-write lock trick
    // All mutative operations MUST be done with the 'this' lock held
    @GuardedBy("this") private volatile int value;

    public int getValue() { return value; }

    public synchronized int increment() {
        return value++;
    }
}
分享到:
评论

相关推荐

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

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

    Java并发编程(5)volatile变量修饰符-意料之外

    总结来说,`volatile`关键字在Java并发编程中起到了关键的作用,但其功能有限,不能替代其他的同步机制。开发者应根据具体场景选择合适的并发工具,以确保数据的正确性和程序的稳定性。在处理复杂的数据结构或涉及...

    Java并发编程:volatile关键字解析

    ### Java并发编程:volatile关键字解析 #### 一、内存模型的相关概念 在深入了解`volatile`关键字之前,我们首先需要理解计算机内存模型的一些基本概念。在现代计算机系统中,CPU为了提高执行效率,会将频繁访问的...

    volatile 变量的说明

    volatile变量在编程语言中,尤其是Java和C/C++中,是一种特殊的标识符,用于指示编译器该变量的值可能在编译器不知情的情况下发生变化。这个关键字的主要作用是告诉编译器不要对这个变量进行优化,每次使用时都需要...

    Java并发编程系列- volatile

    总的来说,`volatile`关键字在Java并发编程中起到的作用是确保共享变量的即时可见性和防止指令重排,但并不保证操作的原子性。理解并合理使用`volatile`可以有效地提升多线程程序的并发性能,但同时也需要注意它的...

    java并发编程实战源码,java并发编程实战pdf,Java

    Java提供了各种手段来实现线程安全,如synchronized关键字、volatile变量、ThreadLocal等。 3. **并发控制**:Java提供了多种并发控制工具,包括synchronized、wait()、notify()、notifyAll()、ReentrantLock(可重...

    Java 并发编程实战.pdf

    在《Java并发编程实战》中,读者也能够了解到如何将并发与现代Java语言特性结合起来,例如使用Lambda表达式和Stream API来简化并发代码的编写。 综合来看,该书不仅适合于对Java并发编程感兴趣的初学者,同样也适合...

    详解java如何正确使用volatile

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

    java并发编程2

    Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...

    Java的并发处理方式

    Java 提供了多种方式来解决并发问题,包括使用锁、同步代码块和 volatile 变量等。 一、什么是并发问题? 并发问题是指多个线程或进程同时访问同一资源所产生的问题。例如,在银行系统中,两个操作员同时操作同一...

    聊聊并发(一)深入分析Volatile的实现原理

    1. **内存可见性**:当一个线程修改了Volatile变量的值,其他线程可以立即看到这个修改。这意味着Volatile变量在被修改后,无需额外的同步操作,其他线程就能获取到最新的值。 2. **禁止指令重排序**:编译器和...

    Java并发编程(18)第五篇中volatile意外问题的

    在Java并发编程中,volatile关键字扮演着至关重要的角色,它提供了线程间的可见性和部分内存屏障,以确保共享变量在多线程环境下的正确性。然而,在实际应用中,开发者可能会遇到一些意料之外的问题,这通常是因为对...

    java并发编程内部分享PPT

    Java提供了多种同步工具,如synchronized关键字、 volatile变量、java.util.concurrent包下的Lock接口(如ReentrantLock)以及Atomic类等。synchronized提供了互斥访问,保证同一时刻只有一个线程执行特定代码段。...

    java 并发编程的艺术pdf清晰完整版 源码

    《Java并发编程的艺术》这本书是Java开发者深入理解并发编程的重要参考书籍。这本书全面地介绍了Java平台上的并发和多线程编程技术,旨在帮助开发者解决在实际工作中遇到的并发问题,提高程序的性能和可伸缩性。 ...

    Java并发编程之volatile变量介绍

    总的来说,volatile变量在Java并发编程中起到的作用是确保多线程环境下数据的可见性,但不能解决原子性问题。开发者需要根据具体的应用场景和需求来决定是否使用volatile,并结合其他的同步工具(如synchronized、...

    Java并发volatile关键字.docx

    Java并发编程中,volatile关键字扮演着重要的角色,它是一种轻量级的同步机制,与synchronized相比,volatile在性能上更优,因为它不会导致线程阻塞。在深入理解volatile的关键特性之前,我们需要先了解Java内存模型...

    2023 java并发编程手册

    "2023 Java并发编程手册" Java 并发编程是指在 Java 语言中编写多线程程序的技术,旨在提高程序的执行效率和响应速度。Java 并发编程手册是 Java 开发者必备的知识储备,以下是 Java 并发编程的关键知识点: 1. ...

    java并发编程与实践

    2. **同步机制**:详述了Java中同步的几种方法,如`synchronized`关键字、volatile变量、Lock接口(如ReentrantLock)以及Condition。这些机制用于防止数据竞争和确保线程安全。 3. **并发工具类**:Java并发包...

    Java并发编程书籍高清版

    例如,书中详细介绍了synchronized关键字的作用、 volatile变量的使用、线程池的创建与管理,以及Future接口和ExecutorService在处理异步任务时的应用。 其次,《java并发编程的艺术》是一本针对Java程序员的实用...

    深入探讨Java多线程中的volatile变量共6页.pd

    本资料《深入探讨Java多线程中的volatile变量》将带你深入理解这个概念,全面解析其工作原理和实际应用。 volatile关键字在Java中主要用于解决多线程环境下的可见性和有序性问题。它确保了被volatile修饰的变量对...

Global site tag (gtag.js) - Google Analytics