static
表示所有对象的值的一个副本,volatile
表示所有线程的值的一个副本,这样说对吗?
无论如何,一个static
变量的值也将是所有线程的一个值,那么我们为什么要 Select volatile
呢?
static
表示所有对象的值的一个副本,volatile
表示所有线程的值的一个副本,这样说对吗?
无论如何,一个static
变量的值也将是所有线程的一个值,那么我们为什么要 Select volatile
呢?
在Java中声明static变量,意味着无论创建了多少个类对象,都只有一个副本.即使不创建Objects
,也可以访问该变量.然而,线程可能有它的本地缓存值.
当变量是volatile而不是static时,每Object
将有一个变量.所以,从表面上看,它似乎与正常变量没有区别,但与static完全不同.但是,即使有Object
个字段,线程也可以在本地缓存变量值.
这意味着,如果两个线程同时更新同一对象的一个变量,并且该变量未声明为volatile,则可能存在这样的情况:其中一个线程的缓存中有一个旧值.
即使通过多个线程访问static个值,每个线程也可以有其本地缓存副本!为了避免这种情况,可以将变量声明为static volatile,这将迫使线程每次读取全局值.
但是,对于正确的同步而言,volatile%不是替身!
例如:
private static volatile int counter = 0;
private void concurrentMethodWrong() {
counter = counter + 5;
//do something
counter = counter - 5;
}
多次同时执行concurrentMethodWrong
可能会导致计数器的最终值不同于零
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
级.