使用 volatile 关键字
据我了解,如果我们将变量声明为易失性,那么它将不会存储在本地缓存中。每当线程更新值时,它都会更新到主内存。因此,其他线程可以访问更新后的值。
但在下面的程序中,易失性和非易失性变量都显示相同的值。
第二个线程的 volatile 变量不会更新。 任何人都可以解释一下为什么 testValue 没有改变。
class ExampleThread extends Thread {
private int testValue1;
private volatile int testValue;
public ExampleThread(String str){
super(str);
}
public void run() {
if (getName().equals("Thread 1 "))
{
testValue = 10;
testValue1= 10;
System.out.println( "Thread 1 testValue1 : " + testValue1);
System.out.println( "Thread 1 testValue : " + testValue);
}
if (getName().equals("Thread 2 "))
{
System.out.println( "Thread 2 testValue1 : " + testValue1);
System.out.println( "Thread 2 testValue : " + testValue);
}
}
}
public class VolatileExample {
public static void main(String args[]) {
new ExampleThread("Thread 1 ").start();
new ExampleThread("Thread 2 ").start();
}
}
output:
Thread 1 testValue1 : 10
Thread 1 testValue : 10
Thread 2 testValue1 : 0
Thread 2 testValue : 0
As i understand, if we declare a variable as volatile, then it will not be stored in the local cache. Whenever thread are updating the values, it is updated to the main memory. So, other threads can access the updated value.
But in the following program both volatile and non-volatile variables are displaying same value.
The volatile variable is not updated for the second thread.
Can anybody plz explain this why testValue is not changed.
class ExampleThread extends Thread {
private int testValue1;
private volatile int testValue;
public ExampleThread(String str){
super(str);
}
public void run() {
if (getName().equals("Thread 1 "))
{
testValue = 10;
testValue1= 10;
System.out.println( "Thread 1 testValue1 : " + testValue1);
System.out.println( "Thread 1 testValue : " + testValue);
}
if (getName().equals("Thread 2 "))
{
System.out.println( "Thread 2 testValue1 : " + testValue1);
System.out.println( "Thread 2 testValue : " + testValue);
}
}
}
public class VolatileExample {
public static void main(String args[]) {
new ExampleThread("Thread 1 ").start();
new ExampleThread("Thread 2 ").start();
}
}
output:
Thread 1 testValue1 : 10
Thread 1 testValue : 10
Thread 2 testValue1 : 0
Thread 2 testValue : 0
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您的变量仅限于单个线程,因此没有其他线程访问它们。因此,
易失性
没有什么区别。如果您将它们声明为
静态
,它们将在不同线程之间共享。但是,即使如此,您也可能无法观察 易失性变量和非易失性变量之间的差异。引自 Java 并发实践,第 1 章。 3.1.4:在您的情况下,代码碰巧首先修改 易失性变量,因此另一个变量的更新值可能对其他线程不可见。到目前为止,一切都很好。
但是,由于您是从修改变量的同一线程中打印变量的值,因此无论如何您都不会看到任何差异。
更新2:尝试这个修改版本(注意:我还没有测试过):
更新:关于静态字段的可见性 - 再次来自同一本书(第16.2.3章) :
Your variables are confined to a single thread, so there is no other thread accessing them. Thus
volatile
makes no difference.If you declared them
static
, they would be shared between different threads. However, even then you may not be able to observe the difference between your volatile and nonvolatile variable. Quote from Java Concurrency in Practice, chap. 3.1.4:In your case, the code happens to modify the volatile variable first, so the updated value of the other variable may not be visible to the other thread. So far, so good.
However, since you are printing out the values of the variables from the same thread which modified them, you won't see any difference anyway.
Update2: Try this modified version (note: I have not tested it):
Update: regarding the visibility of static fields - again from the same tome (chap 16.2.3):
这与
易失性
无关;它们是ExampleThread
的两个独立实例,具有自己的testValue1
和testValue
副本,它们是实例字段(不是static
) code> 类变量,在所有实例之间“共享”)。This has nothing to do with
volatile
; those are two separate instances ofExampleThread
, with their own copies oftestValue1
andtestValue
, which are instance fields (notstatic
class variables, which are "shared" between all instances).ExampleThread 1 和ExampleThread 2 是不同的对象。
在其中一个中,您将 10 分配给两个 int 字段,这就是您看到第一个线程的输出的原因。
第二,你没有给 int 字段分配任何东西,所以你得到 0。
ExampleThread 1 and ExampleThread 2 are different objects.
In one of them you assigned 10 to both int fields and that's why you see that output for first thread.
In second you didn't assign anything to int fields so you get 0s.
您可能丢失了static关键字吗?
May be you lost static keyword?
testValue
是一个成员变量,因此两个线程看到两个独立的副本。当两个或多个线程引用同一对象时,易失性
是相关的。使testValue静态和易变才会有效果。但是,您可能不会(也可能不会)看到这种效果,因为它高度依赖于时间、调度和缓存策略,而这些策略超出了您(甚至虚拟机)的控制范围。缺少 volatility 很少会产生影响,这使得此类错误很难被发现。仅当一个线程更新该值并且第二个线程读取该值并且该值仍在两个线程中的任何一个的缓存中时才会看到它。
testValue
is a member variable, so the two threads see two independent copies.volatile
is relevant when two or more threads have a reference to the same object.Make testValue static and volatile will have an effect. However, you may not (and probably will not) see that effect, as it is highly dependent on timing, scheduling and caching strategies which are out of your (or even the VM's) control. A missing volatile will only rarely have an effect, which makes such bugs very hard to catch. It will only be seen when a thread updates the value and the second thread reads the value and the value is still in the cache in either of the two threads.
下面是一个示例,显示由两个线程访问的变量。
StarterThread
线程在线程启动时设置变量started
。WaiterThread
等待变量started
被设置。如果
started
不是易失性的,则没有同步点可以保证WaiterThread
将获得started
变量的更新值。因此,WaiterThread
线程可能会“无限期”运行。Here is an example showing a variable that is accessed by two threads. The
StarterThread
thread sets the variablestarted
when the thread starts. TheWaiterThread
waits for the variablestarted
to be set.If
started
is not volatile, then there is no synchronization point that guarantees thatWaiterThread
will ever get the updated value of thestarted
variable. Consequently, theWaiterThread
thread could potentially run "indefinitely".