Java 中的可变与静态 [英] Volatile vs Static in Java

查看:20
本文介绍了Java 中的可变与静态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

static 表示所有对象的值的一个副本而volatile 表示所有线程的值的一个副本是否正确?

Is it correct to say that static means one copy of the value for all objects and volatile means one copy of the value for all threads?

无论如何,static 变量值也将是所有线程的一个值,那我们为什么要使用 volatile 呢?

Anyway a static variable value is also going to be one value for all threads, then why should we go for volatile?

推荐答案

在Java中声明一个static变量,意味着无论创建多少个类的对象,都只会有一个副本.即使根本没有创建Objects,该变量也可以访问.但是,线程可能在本地缓存了它的值.

Declaring a static variable in Java, means that there will be only one copy, no matter how many objects of the class are created. The variable will be accessible even with no Objects created at all. However, threads may have locally cached values of it.

当一个变量是易失性而不是静态时,每个Object都会有一个变量.因此,从表面上看,它似乎与普通变量没有区别,但与静态完全不同.但是,即使使用 Object 字段,线程也可能会在本地缓存变量值.

When a variable is volatile and not static, there will be one variable for each Object. So, on the surface it seems there is no difference from a normal variable but totally different from static. However, even with Object fields, a thread may cache a variable value locally.

这意味着如果两个线程同时更新同一个 Object 的变量,并且该变量没有声明为 volatile,则可能存在其中一个线程缓存旧值的情况.

This means that if two threads update a variable of the same Object concurrently, and the variable is not declared volatile, there could be a case in which one of the thread has in cache an old value.

即使您通过多个线程访问静态值,每个线程都可以拥有其本地缓存副本!为避免这种情况,您可以将变量声明为 static volatile,这将强制线程每次读取全局值.

Even if you access a static value through multiple threads, each thread can have its local cached copy! To avoid this you can declare the variable as static volatile and this will force the thread to read each time the global value.

但是,volatile 不能替代适当的同步!
例如:

However, volatile is not a substitute for proper synchronisation!
For instance:

private static volatile int counter = 0;

private void concurrentMethodWrong() {
  counter = counter + 5;
  //do something
  counter = counter - 5;
}

同时多次执行 concurrentMethodWrong 可能会导致 counter 的最终值不为零!
要解决这个问题,你必须实现一个锁:

Executing concurrentMethodWrong concurrently many times may lead to a final value of counter different from zero!
To solve the problem, you have to implement a lock:

private static final Object counterLock = new Object();

private static volatile int counter = 0;

private void concurrentMethodRight() {
  synchronized (counterLock) {
    counter = counter + 5;
  }
  //do something
  synchronized (counterLock) {
    counter = counter - 5;
  }
}

或者使用AtomicInteger 类.

Or use the AtomicInteger class.

这篇关于Java 中的可变与静态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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