【问题标题】:volatile multi-threading data inconsistency不稳定的多线程数据不一致
【发布时间】: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


【解决方案1】:

是的,我的错,我发现了这个错误,我在未处理事件实际被处理之前减少了它们的值,这意味着测试触发到早期,并且有时 lastPrintln 没有更新。谢谢你们的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-30
    • 1970-01-01
    相关资源
    最近更新 更多