- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
根据这个问题的答案( Java volatile array? ),我做了以下测试:
public class Test {
public static volatile long[] arr = new long[20];
public static void main(String[] args) throws Exception {
new Thread(new Thread(){
@Override
public void run() {
//Thread A
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
arr[19] = 2;
}
}).start();
new Thread(new Thread(){
@Override
public void run() {
//Thread B
while (arr[19] != 2) {
}
System.out.println("Jump out of the loop!");
}
}).start();
}
}
据我所知,对于数组对象,volatile
关键字仅保证arr引用的可见性,不保证数组中元素的可见性。然而当线程A改变了arr[19]时,线程B发现了arr[19]的变化并跳出了循环。
那么问题出在哪里呢?
最佳答案
让我首先对您的示例进行修改:
public class Test {
public static long[] arr = new long[20]; // Make this non-volatile now
public static volatile int vol = 0; // Make another volatile variable
public static void main(String[] args) throws Exception {
new Thread(new Thread(){
@Override
public void run() {
//Thread A
try {
TimeUnit.MILLISECONDS.sleep(1000);
arr[19] = 2;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Thread(){
@Override
public void run() {
//Thread B
while (true) {
int i = vol;
if (arr[19] == 2) {
break;
}
}
System.out.println("Jump out of the loop!");
}
}).start();
}
}
你会意识到这也会导致线程 B 跳出循环(除非这个症状是 JIT 特有的,而我的恰好就是这样做的)。神奇之处就在于这个int i = vol;
——或者更准确地说,读取一个 volatile
变量。删除该行将导致线程 B 无限地停留在循环内。
因此,似乎对 volatile
变量的任何读取(即任何 volatile 读取)似乎都会检索最新的值(包括其他非 volatile 值)。
我尝试研究 JLS,但它太复杂,我无法完全理解。我看到一篇文章here描述了可见性保证。
摘自文章:
If Thread A reads a
volatile
variable, then all all variables visible to Thread A when reading thevolatile
variable will also be re-read from main memory.
(忽略文章中“all all”的拼写错误。)
在这种情况下,当线程读取 volatile
变量时,似乎主内存中的所有数据都会更新回CPU缓存。
其他有趣的发现:如果您向线程 B 添加另一个 Thread.sleep()
(例如 sleep 50 毫秒),即使没有读取 volatile <,循环也会设法退出
变量。令人惊讶JLS 17.3声明如下:
It is important to note that neither Thread.sleep nor Thread.yield have any synchronization semantics. In particular, the compiler does not have to flush writes cached in registers out to shared memory before a call to Thread.sleep or Thread.yield, nor does the compiler have to reload values cached in registers after a call to Thread.sleep or Thread.yield.
我再次不确定此症状是 JIT 还是 JRE 特定的。
关于java volatile 数组,我的测试结果与预期不符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53753792/
下面的代码应该显示我的表格中的随机帖子;它执行此操作,但它显示的帖子的 ID 与 URL 中的 ID 不同。 如何让它显示 URL 中的内容?谢谢。 $db = new PDO('mysql:host
我有一个自定义类,其中覆盖了 equals() 和 hashCode() 方法。我将该类的实例存储在 TreeSet 中。我无法弄清楚为什么 tree.contains(someObject) 返回
我正在尝试通过使用代码请求对healthkit中类别的授权: let healthKitStore: HKHealthStore = HKHealthStore() let healthKitType
我的代码的相关部分: 模型架构: Sequential( layers=[ BatchNormalization(input_shape=input_shape),
我是一名优秀的程序员,十分优秀!