何时使用挥发性改性剂?

Rak*_*ami 3 java volatile

可能重复:
您何时在Java中使用volatile关键字?

什么时候和为什么在java中需要volatile修饰符?

我有兴趣看到volatile变体原语或对象引用的真实世界用法.

Vin*_*non 7

volatile修饰符将告诉JVM对并发运行的线程持谨慎态度.本质上,volatile用于指示变量的值将被不同的线程修改.

声明一个易变的Java变量意味着:

  • 这个变量的值永远不会被线程本地缓存:所有读写都将直接进入"主存"

  • 对变量的访问就像包含在同步块中一样,自身同步.

我们在第二点说"好像",因为至少对程序员来说(并且可能在大多数JVM实现中)没有涉及实际的锁对象.


挥发性修饰符告诉挥发性修改的变量可以通过程序的其他部分意外更改的编译器.其中一种情况涉及多线程程序.

在多线程程序中,有时两个或多个线程共享同一个实例变量.出于效率考虑,每个线程可以保留这种共享变量的私有副本.

变量的实际(或主)副本在不同时间更新,例如在输入同步方法时.虽然这种方法工作正常,但有时可能效率低下.在某些情况下,所有真正重要的是变量的主副本始终反映其当前状态.

为了确保这一点,只需将变量指定为volatile,它告诉编译器它必须始终使用volatile变量的主副本(或者,至少始终保持任何私有副本与主副本保持同步,反之亦然) .此外,必须按照在任何私有副本上执行它们的精确顺序执行对主变量的访问.


Sub*_*der 6

如果您正在使用多线程编程,那么volatile关键字将更有用.当多个线程使用相同的变量时,每个线程将拥有自己的该变量的本地缓存副本.因此,当它更新值时,它实际上在本地缓存中更新,而不是在主变量内存中更新.使用相同变量的另一个线程对另一个线程更改的值一无所知.要避免此问题,如果将变量声明为volatile,则不会将其存储在本地缓存中.每当线程更新值时,它都会更新到主存储器.因此,其他线程可以访问更新的值.

声明变量volatile意味着

  • 没有缓存维护意味着在主内存中进行所有更改.
  • 对此变量的访问充当同步块,即使它处于同步单元中.

示例 -

public class Snippet implements Runnable{
volatile int num =0;

public void run(){
    Thread t = Thread.currentThread();
    String name = t.getName();
    if(name.equals("Thread1")){
        num=10;
    }
    else{
        System.out.println("value of num is :"+num);
    }

}
public static void main(String args[]) throws InterruptedException{
    Runnable r = new Snippet();
    Thread t1 = new Thread(r);
    t1.setName("Thread1");
    t1.start();

    Thread.sleep(1000);

    Thread t2 = new Thread(r);
    t2.setName("Thread2");
    t2.start();
}
 }
Run Code Online (Sandbox Code Playgroud)