Java中的易失性关键字 - 澄清 [英] Volatile keyword in Java - Clarification

查看:106
本文介绍了Java中的易失性关键字 - 澄清的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的很困惑我读到的关于java中volatile关键字的应用程序。

I am really confused about what I read about the applications of volatile keyword in java.


  1. 以下语句是否正确?
    在每次后续读取相同字段之前发生对易失性字段的写入

  1. Is the following statement correct? "a write to a volatile field happens before every subsequent read of the same field"

理想情况下应该何时使用volatile关键字?

Ideally when should volatile keyword used?

有什么区别:

class TestClass
{  private int x;

   synchronized int get(){return x;}
   synchronized void set(int x){this.x = x;}

}


class TestClass
{  private volatile int x;

   int get(){return x;}
   void set(int x){this.x = x;}

}


推荐答案

volatile 字段修饰符,而同步修改代码块方法。因此,我们可以使用这两个关键字指定简单访问器的三种变体:

volatile is a field modifier, while synchronized modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords:

     int i1;
     int geti1() {return i1;}

     volatile int i2;
     int geti2() {return i2;}

     int i3;
     synchronized int geti3() {return i3;}

geti1 ()访问当前线程中当前存储在 i1 中的值。
线程可以拥有变量的本地副本,并且数据不必与其他线程中保存的数据相同。特别是,另一个线程可能已更新 i1 在它的线程中,但当前线程中的值可能与更新的值不同。事实上,Java有一个主内存的概念,这是保存变量当前正确值的内存。线程可以拥有自己的变量数据副本,并且线程副本可以与主内存不同。事实上,对于<1 c $ c> i1 ,主内存可能具有 1 的值,因为thread1的值为< i1 的强> 2 , thread2 3 <$ c $的值 3 c> i1 如果 thread1 thread2 都更新了i1但这些更新后的值尚未传播到主内存或其他线程。

geti1() accesses the value currently stored in i1 in the current thread. Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads.In particular, another thread may have updated i1 in it's thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a "main" memory, and this is the memory that holds the current "correct" value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the "main" memory. So in fact, it is possible for the "main" memory to have a value of 1 for i1, for thread1 to have a value of 2 for i1 and for thread2 to have a value of 3 for i1 if thread1 and thread2 have both updated i1 but those updated value has not yet been propagated to "main" memory or other threads.

另一方面, geti2()有效地访问 i2的值。不允许volatile变量具有与main内存中当前保存的值不同的变量的本地副本。实际上,声明为volatile的变量必须使其数据在所有线程之间同步,因此无论何时在任何线程中访问或更新变量,所有其他线程都会立即看到相同的值。通常,volatile变量比普通变量具有更高的访问和更新开销。通常,允许线程拥有自己的数据副本以提高效率。

On the other hand, geti2() effectively accesses the value of i2 from "main" memory. A volatile variable is not allowed to have a local copy of a variable that is different from the value currently held in "main" memory. Effectively, a variable declared volatile must have it's data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Generally volatile variables have a higher access and update overhead than "plain" variables. Generally threads are allowed to have their own copy of data is for better efficiency.

volitile和synchronized之间存在两个区别。

There are two differences between volitile and synchronized.

首先同步获取并释放监视器上的锁定,这些锁定一次只能强制一个线程执行代码块。这是同步的众所周知的方面。但同步也同步内存。实际上,synchronized将整个线程内存与主内存同步。因此执行 geti3()执行以下操作:

Firstly synchronized obtains and releases locks on monitors which can force only one thread at a time to execute a code block. That's the fairly well known aspect to synchronized. But synchronized also synchronizes memory. In fact synchronized synchronizes the whole of thread memory with "main" memory. So executing geti3() does the following:


  1. 线程获取锁定对象的监视器。

  2. 线程内存刷新所有变量,即它的所有变量都有效地从主内存中读取。

  3. 执行代码块(在这种情况下,将返回值设置为i3的当前值,可能刚刚从main内存重置)。

  4. (对变量的任何更改)现在通常会被写入主内存,但是对于geti3(),我们没有任何更改。)

  5. 线程在监视器上释放对象锁定。

  1. The thread acquires the lock on the monitor for object this .
  2. The thread memory flushes all its variables, i.e. it has all of its variables effectively read from "main" memory .
  3. The code block is executed (in this case setting the return value to the current value of i3, which may have just been reset from "main" memory).
  4. (Any changes to variables would normally now be written out to "main" memory, but for geti3() we have no changes.)
  5. The thread releases the lock on the monitor for object this.

因此,volatile只在线程内存和主内存之间同步一个变量的值,同步同步所有变量的值线程内存和主内存,并锁定和释放监视器以引导。明确同步可能比volatile更具开销。

So where volatile only synchronizes the value of one variable between thread memory and "main" memory, synchronized synchronizes the value of all variables between thread memory and "main" memory, and locks and releases a monitor to boot. Clearly synchronized is likely to have more overhead than volatile.

http://javaexp.blogspot.com/2007/12/difference-between-volatile-and.html

这篇关于Java中的易失性关键字 - 澄清的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆