Java 易失性多线程数据不一致性

Java 易失性多线程数据不一致性,java,multithreading,volatile,Java,Multithreading,Volatile,我以为我已经采取了必要的措施来防止数据竞争,但它似乎没有起作用 我编写了一个分层状态机来实现一个硬币问答游戏。 我的一个JUnit测试检查打印到屏幕上的最后一行是否是预期的,因为刚刚处理了一个信用事件。 我发现行确实像预期的那样打印在屏幕上,但是用于存储最后打印值的字符串在测试点为空 我已经确保字符串引用是volatile,因此我希望事件处理线程的写操作对JUnit线程上的读操作可见 machine类包含事件处理循环和以下用于读取和写入字符串引用的代码: private volatile Str

我以为我已经采取了必要的措施来防止数据竞争,但它似乎没有起作用

我编写了一个分层状态机来实现一个硬币问答游戏。 我的一个JUnit测试检查打印到屏幕上的最后一行是否是预期的,因为刚刚处理了一个信用事件。 我发现行确实像预期的那样打印在屏幕上,但是用于存储最后打印值的字符串在测试点为空

我已经确保字符串引用是volatile,因此我希望事件处理线程的写操作对JUnit线程上的读操作可见

machine类包含事件处理循环和以下用于读取和写入字符串引用的代码:

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没有更新的时候。谢谢你们的帮助。