【发布时间】:2013-05-25 13:42:08
【问题描述】:
我以为我已经采取了必要的措施来防止数据竞争,但它似乎没有奏效......
我编写了一个分层状态机来实现硬币问答游戏。 鉴于刚刚处理了信用事件,我的一个 JUnit 测试检查是否需要打印到屏幕的最后一行。 我发现该行确实按预期打印在屏幕上,但是用于存储最后一个打印值的字符串在测试时为空。
我已经确定字符串引用是volatile,所以我希望来自事件处理线程的写入对 JUnit 线程上的读取是可见的。
机器类包含事件处理循环和以下用于读取和写入字符串引用的代码:
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());
}
【问题讨论】:
-
我看不到
println(String)方法的调用位置。如果字符串是null,那么在调用lastPrintln()之前不会调用该方法。我会在println(String)中设置一个断点。 -
你的 JDK 版本是多少? volatile 的行为与 1.5 不同。
-
println(String) 在事件循环中被调用并且具有非空值。我正在使用 1.7
-
请显示调用
println(String)的代码以及从事件队列中删除事件的位置。 -
是的,我的错,我发现了这个错误,我在未处理事件实际处理之前降低了它们的值,这意味着测试触发到早期,并且有时 lastPrintln 没有更新.谢谢你们的帮助。
标签: java multithreading volatile