我有一个自定义日志,该日志获取由后台线程或由用户鼠标单击事件触发的主线程打印的数据。这两个线程可以同时在日志上打印。代码是这样的

public void appendLine(String s, int type) {
    synchronized (this) {
        int index = setInputLine(s);
        if (type == BG) {
            updateConsole();
        }
        else if (type == UI) {
            printConsole();
        }
    }
}


方法setInputLines(),updateConsole()和printConsole()未定义为已同步。方法updateConsole()这样从后台线程打印

public void updateConsole() {
    Display.syncExec(new Runnable() {
        // update widgets UI here
    });
}


但是,以上代码逻辑在测试中失败。从测试后台线程调用方法appendLine(),当主线程尝试通过并发调用appendLine()来获取锁时,方法总是挂在Display.syncExec()上。有人知道为什么吗?谢谢

最佳答案

Display.syncExec将阻塞调用它的线程,直到它可以运行为止-直到下一次UI线程在主UI循环中调用Display.readAndDispatch时,它才会阻塞。

如果主UI线程在运行appendLine之前调用readAndDispatch,则该UI线程将被阻塞,等待synchronized块,然后出现死锁。

因此从这样的同步块中调用syncExec是不安全的。

您可能可以使用asyncExec而不是syncExec,因为这不会阻塞线程。

09-26 11:17