我有一个简单的Jc应激测试:
package io.denery;
import org.openjdk.jcstress.annotations.*;
import org.openjdk.jcstress.infra.results.IIII_Result;
@JCStressTest
@Outcome(expect = Expect.ACCEPTABLE_INTERESTING)
@State
public class RaceIRIWTest {
volatile int x, y;
@Actor
public void actor1() {
x = 1;
}
@Actor
public void actor2() {
y = 1;
}
@Actor
public void actor3(IIII_Result r) {
r.r1 = x;
r.r2 = y;
}
@Actor
public void actor4(IIII_Result r) {
r.r3 = y;
r.r4 = x;
}
}但这项测试的结果是:
OK io.denery.RaceIRIWTest (JVM args:-XX:+UnlockDiagnosticVMOptions,-XX:+WhiteBoxAPI,-XX:-RestrictContended,-Dfile.coding=UTF-8,-Duser.country=RU,-Duser.language=en,-Duser.variant,-XX:-TieredCompilation,-XX:+StressLCM,-XX:+StressGCM,-XX:+StressIGVN)观察到状态事件的期望解释
0,0,0,0,0 22,180,923 ACCEPTABLE_INTERESTING
0,0,0,1721,581 ACCEPTABLE_INTERESTING
0,0,1,0 13,347 ACCEPTABLE_INTERESTING
0,0,1,1 456,971 ACCEPTABLE_INTERESTING
0,1,0,0,0 344,068 ACCEPTABLE_INTERESTING
0,1,0,1 36 ACCEPTABLE_INTERESTING
0,1,1,0 528,641 ACCEPTABLE_INTERESTING
0,1,1,1258,265 ACCEPTABLE_INTERESTING
1,0,0,0,0 204,088 ACCEPTABLE_INTERESTING
1,0,0,1 667,580 ACCEPTABLE_INTERESTING
1,0,1,1 94,877 ACCEPTABLE_INTERESTING
1,1,0,0 663,159 ACCEPTABLE_INTERESTING
1,1,0,1 306,251 ACCEPTABLE_INTERESTING
1,1,1,0 128,608 ACCEPTABLE_INTERESTING
1,1,1,1 18,838,186 ACCEPTABLE_INTERESTING
我们看到了竞争条件,但是如果我将static放到volatile int x, y中并删除volatile关键字,那么jc应激测试的结果将是:
OK io.denery.RaceIRIWTest (JVM args:-XX:+UnlockDiagnosticVMOptions,-XX:+WhiteBoxAPI,-XX:-RestrictContended,-Dfile.coding=UTF-8,-Duser.country=RU,-Duser.language=en,-Duser.variant,-XX:-TieredCompilation,-XX:+StressLCM,-XX:+StressGCM,-XX:+StressIGVN)观察到状态事件的期望解释
1,1,1,1 100,299,061 ACCEPTABLE_INTERESTING
为什么不修复竞争条件,但静态关键字修复它?还是Jc应激的问题?
发布于 2021-10-11 06:14:34
我不是JCStress专家。
但是您所缺少的是,您需要指定法律结果,请参阅下面的链接以获得一个示例。
禁例
在IRIW测试中,您希望防止不同CPU对不同地址的存储出现故障。因此,您希望防止参与者3看到r1=1, r2=0 (在y之前看到x )。演员4看到r3=1, r4=0 ( y在x之前也是如此)。所以被禁止的案例是1,0,1,0
易失性
当我用易失性检查结果时,不会遇到禁止的情况。其原因是,带有volatile的示例不存在数据竞争,因此它只产生连续一致(SC)执行。对于SC,在加载/存储上总是会有一些总订单来解释执行。由于有一个总订单,它还将订购存储到不同的地址,由不同的CPU发出。此外,SC将防止负载被重新排序,因为SC执行需要与程序顺序(PO)保持一致。
静态不挥发
带有静态的示例包含一个数据竞赛,因为在读和写之间的边界之前没有发生。因此,只有使用静态时,才允许查看禁止执行的1,0,1,0。
一个简单的解释是,如果JIT或CPU允许无序负载(例如ARM),那么JIT或CPU会重新排序这两个负载。我的猜测是,您只看到1,1,1,1,因为x和y并没有被JCStress取消设置;但是,我对JCStress还不够了解。
多余
为了使这个例子更有趣,我将使两个商店变得不透明,加载不透明的负载,并在这两个负载之间设置一个LoadLoad围栏,以确保它们按照顺序执行。不透明将确保加载/存储不会被优化,它将提供原子性(基本保证),但不会为不同地址的加载/存储提供任何排序保证。因此,您将测试CPU的内存一致性保证。
IRIW不应该在现代CPU上失败,因为它们是多拷贝原子的,我所知道的唯一能够显示这种行为的CPU就是PowerPC。
https://stackoverflow.com/questions/69517384
复制相似问题