我想知道JMM是否允许实现重新排序对ai
和ada
变量的访问,其行为与代码中显示的意图不同。
目的是执行ops的方法是下一个:
索引达到1000后会发生什么对我来说并不重要。我实际上想要将数组用作环,但如果这个问题得到解答,我将能够弄清楚如何做到这一点。
基本上我想避免锁定并依赖原子和无锁对象。但我不知道在这种特殊情况下我是否还需要隐式同步。
AtomicInteger ai = new AtomicInteger(0);
// let's say all values are null by default
AtomicDoubleArray ada = new AtomicDoubleArray(1000);
int rn = 4; // dice rolled...
void perfomOps(AtomicInteger ai, AtomicDoubleArray ada) {
int i = ai.getAndIncrement();
ada.set(i, rn);
spinlock(ada, i);
printSum(ada, i);
}
void spinlock(AtomicDoubleArray ada, int idx) {
// spinlock in case the other threads couln't write to older indexes yet
if (idx > 0)
for (int c = 0;c < idx; c++)
while (i = ada.get(c) == null);
}
void printSum(AtomicDoubleArray ada, int idx) {
double sum = 0;
for (int i = 0;i < idx; i++)
sum = sum + ada.get(i);
Sytem.out.println(sum);
}
// thread 1
perfomOps(ai, ada); // lets say we get 4 printed
// thread 2
perfomOps(ai, ada); // lets say we get 8 printed
// thread 3
perfomOps(ai, ada); // lets say we get 12 printed
其他线程将继续这样做,可能会发生打印顺序不符合预期,如8,12和4。但假设下一个线程进来,那么它将看到正确的值并正确打印16
所有这些花哨的东西都是为了避免显式锁定以测量哪一个表现更好,无锁版本或同步版本
答案 0 :(得分:3)
Java内存模型最重要的规则是(§17.4.5):
当且仅当所有顺序一致的执行没有数据争用时,程序才能正确同步。如果程序正确同步,则程序的所有执行都将显示为顺序一致(第17.4.3节)。
如果所有共享变量都是 volatile 或 atomic ,那么就没有数据竞争。这意味着sequential consistency得到保证。这意味着,在程序的行为中不会出现重新排序。