是否递增运算符,例如count++;在本地存储易失性数据线程?
我的目标是了解 volatile 关键字的工作原理。
我的预期结果: assertEquals 没有失败。
我的实际结果: assertEquals 失败。(有时实际计数值在 9991 到 9999 之间)。
我假设这是因为增量运算符 /count++等于
public void increment() {
int temp = count;
count = temp + 1;
}
考虑到这一点,该temp属性是线程本地存储的。我是真的吗?
计数器.java
public class Counter implements Runnable {
private volatile int count = 0;
public int getCount() { return count; }
public void increment() { count++; }
@Override
public void run() { increment(); }
}
CounterTest.java
public class CounterTest {
@Test
void increment() {
ExecutorService service = Executors.newFixedThreadPool(10);
Counter counter = new Counter();
for (int i = 0; i < 10000; i++) {
service.execute(counter);
}
service.shutdown();
service.awaitTermination(1, TimeUnit.SECONDS);
assertEquals(10000, counter.getCount());
}
}
回答
我的目标是了解 volatile 关键字的工作原理
如果这是您的目标,那么请开始查看提供JLS的保证volatile。volatile是不是关于原子操作,即:count++;不是原子。因此,这:
assertEquals(10000, counter.getCount());
可能会在任何时间点失败。
volatile是关于某个线程在观察到另一个线程对该变量的写入值时应该“观察”的内容。有很多,字面意思是这意味着什么的例子,可能最著名的一个 是 this。从那里开始,将您的知识积累到JLS.