Java 易失性多线程数据不一致性
我以为我已经采取了必要的措施来防止数据竞争,但它似乎没有起作用 我编写了一个分层状态机来实现一个硬币问答游戏。 我的一个JUnit测试检查打印到屏幕上的最后一行是否是预期的,因为刚刚处理了一个信用事件。 我发现行确实像预期的那样打印在屏幕上,但是用于存储最后打印值的字符串在测试点为空 我已经确保字符串引用是volatile,因此我希望事件处理线程的写操作对JUnit线程上的读操作可见 machine类包含事件处理循环和以下用于读取和写入字符串引用的代码:Java 易失性多线程数据不一致性,java,multithreading,volatile,Java,Multithreading,Volatile,我以为我已经采取了必要的措施来防止数据竞争,但它似乎没有起作用 我编写了一个分层状态机来实现一个硬币问答游戏。 我的一个JUnit测试检查打印到屏幕上的最后一行是否是预期的,因为刚刚处理了一个信用事件。 我发现行确实像预期的那样打印在屏幕上,但是用于存储最后打印值的字符串在测试点为空 我已经确保字符串引用是volatile,因此我希望事件处理线程的写操作对JUnit线程上的读操作可见 machine类包含事件处理循环和以下用于读取和写入字符串引用的代码: private volatile Str
private volatile String lastPrintln;
public String lastPrintln(){
return lastPrintln;
}
void println(String s){
System.out.println(s);
lastPrintln = s;
}
测试代码如下
@Before
public void setUp() throws Exception {
machine = Objects.create(CoinQuizMachine.class);
machine.start(); // starts event loop thread
}
private void waitForEventQueueToEmpty(){
while(!machine.eventQueueIsEmpty()){
}
}
private void processTestEvent(Event e){
machine.add(e);
waitForEventQueueToEmpty();
}
@Test
public void test2() {
assertEquals(Demo.class,machine.activeState().getClass());
processTestEvent(new CreditEvent(1));
assertEquals("Topic Choices: \nMaths\nScience",machine.lastPrintln());
}
是的,我错了,我发现了这个bug,我在未处理的事件被实际处理之前就降低了它们的值,这意味着测试被提前触发,并且在lastPrintln没有被更新的时候触发。谢谢你们的帮助。我不知道在哪里调用
println(String)
方法。如果字符串为null
,则在调用lastPrintln()
之前不会调用该方法。我会在println(String)
中设置一个断点。您的JDK版本是什么?volatile的行为与1.5不同。println(String)在事件循环中被调用,并且具有非null值。我使用的是1.7请显示调用println(String)
的代码,以及从事件队列中删除事件的代码。是的,我发现了错误,我在未处理事件实际处理之前降低了它们的值,这意味着测试提前触发,在最后的println没有更新的时候。谢谢你们的帮助。