我目前正试图研究并发性,特别是“volatile”关键字。Java - 易失性不按预期工作
通过声明计数器变量挥发性所有写计数器变量将被立即写回主内存。此外,计数器变量的所有读取都将直接从主存储器读取。这里是计数器变量的volatile声明的外观
和
当一个线程写入volatile变量,那么不只是volatile变量本身被写入主存储器。在写入volatile变量之前,线程更改的所有其他变量也会刷新到主内存中。当一个线程读取一个易失变量时,它还会读取主内存中与易失变量一起刷新到主内存中的所有其他变量。
来源:tutorials.jenkov.com | Java Concurrency - Java Volatile Keyword
这使我得出结论/假设,我做出一个volatile变量的任何变化都会永远是所有线程可见。所以,我做了一个代码来测试它。
TestClass
package org.personal.test1;
class TestClass {
public static int w = 0;
public static int x = 0;
public static int y = 0;
public static volatile int z = 0;
private static final int ITERATIONS = 100000;
public static void sooPlus(int indents) {
for (int i = 0; i < TestClass.ITERATIONS; i++) {
TestClass.w++;
TestClass.x++;
TestClass.y++;
TestClass.z++;
}
}
public static void sooMinus(int indents) {
for (int i = 0; i < TestClass.ITERATIONS; i++) {
TestClass.w--;
TestClass.x--;
TestClass.y--;
TestClass.z--;
}
}
public static synchronized String getVariableValues() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("(");
stringBuilder.append("w : "+TestClass.w+", ");
stringBuilder.append("x : "+TestClass.x+", ");
stringBuilder.append("y : "+TestClass.y+", ");
stringBuilder.append("z : "+TestClass.z+")");
return stringBuilder.toString();
}
}
Main Class
package org.personal.test1;
/**
* <ol type="I">
* <li>
* <a href="http://tutorials.jenkov.com/java-concurrency/volatile.html">jenkov.com - Java Volatile Keyword</a>
* </li>
* </ol>
*/
public class Main {
public static void main(String[] args) {
Main.call1();
}
private static void call1() {
Main.test1();
}
private static void test1() {
Thread thread1 = new Thread("Thread1") {
@Override
public void run() {
TestClass.sooPlus(1);
}
};
Thread thread2 = new Thread("Thread2") {
@Override
public void run() {
TestClass.sooMinus(4);
}
};
thread1.start();
thread2.start();
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(TestClass.getVariableValues());
}
}
我得到的结果不是我所期待的。
我得到什么(变化)
(w : -2314, x : -1692, y : -1416, z : -1656)
我很期待
(w : 0, x : 0, y : 0, z : 0)
或至少
(w : -2314, x : -1692, y : -1416, z : 0)
的问题
- 我是怎么假设/推断错误,导致不同的输出少于预期?
- 我的测试方法不正确?如果是,那我该如何解决?
- (可选)有什么好的Java并发性教程,你推荐?
注意
- 我没有尝试读取类似的问题,但我没能完全理解提问者试图以了解他的问题做。
volatile关键字提供了一种弱的线程安全形式。它保证可见性,但不是原子性或互斥。是否可能会使易变的字段不是线程安全的?是的,如果写入字段不是原子的。由所有易失性字段组成的类是否可能不是线程安全的?是的,如果写入字段导致无效状态转换(由于缺乏同步)。 – scottb