static
表示所有对象的值的一份副本,volatile
表示所有线程的值的一份副本是否正确?
反正static
变量值也将是所有线程的一个值,那我们为什么要选择volatile
?
在Java中声明一个static变量,意味着无论创建多少类对象,都只会有一个副本。即使根本没有创建 Objects
,也可以访问该变量。但是,线程可能有它的本地缓存值。
当变量是volatile而不是static时,每个Object
都会有一个变量。所以,表面上看起来与普通变量没有区别,但与静态完全不同。但是,即使有 Object
字段,线程也可以在本地缓存变量值。
这意味着如果两个线程同时更新同一个 Object 的变量,并且该变量未声明为 volatile,则可能存在其中一个线程缓存旧值的情况。
即使您通过多个线程访问 静态 值,每个线程也可以拥有其本地缓存副本!为避免这种情况,您可以将变量声明为 static volatile,这将强制线程每次读取全局值。
但是,volatile 不能代替正确的同步!
例如:
private static volatile int counter = 0;
private void concurrentMethodWrong() {
counter = counter + 5;
//do something
counter = counter - 5;
}
多次并发执行concurrentMethodWrong
可能导致counter的最终值不为零!
要解决这个问题,你必须实现一个锁:
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
类。
我是一名优秀的程序员,十分优秀!