swingWorker调用的synchronized方法中断了吗?

synchronized method called by swingWorker interrupted?

我有一个同步函数,它是从另一个函数的循环在新线程中启动的,并且有很多调用它。所以我有:

foo(){
new SwingWorker() {
                @Override
                public void doInBackground() {
                    sync_foo();
                }
            }.execute();
} catch (IOException e) {
            log.error("", e);
        }
}

sync_foo 定义为:

private synchronized void sync_foo() {
}

我在 sync_foo 中放置了一些调试行以检查它是否按预期工作。所以我有:

private synchronized void sync_foo() {
    final Logger log = Logger.getLogger(getClass());
    log.info("start");
    ...
    log.info("finish");
}

这里的记录器是Log4J,据我所知确实是线程安全的。我注意到在日志文件中有时会有两个后续 "start"。所以我在末尾 log.info("still alive") 附近又加了一行,并让它越来越接近 log.info("start"); 看看我是否停止获得双 starts 并且总是在 still alive 之间两个,但我还是明白了,最后我把它放在 log.info("start"); 的下一行:

private synchronized void sync_foo() {
    final Logger log = Logger.getLogger(getClass());
    log.info("start");
    log.info("still alive");
    ...
    log.info("finish");
}

但时不时地,我仍然得到:

start
start

我觉得很费解。看来该方法以某种方式被打断了,但我不明白是如何打断的。我应该补充一点,sync_foo() 仅从 foo() 调用,我没有收到任何异常或任何类型的错误。

所以问题是:

同步依赖于共享锁,因此如果您看到多个线程调用并发同步的东西的行为,这意味着它们没有使用同一个锁。听起来 sync_foo 是在不同的对象上调用的。在方法上使用 synchronized 意味着对象实例上的监视器由想要进入该方法的线程获取,因此如果在不同的对象上调用该方法,则没有共享锁,也没有什么可以阻止线程进入一个对象上的方法,而另一个线程正在另一个对象上执行该方法。

你可以像这样创建一个 class 级别的锁:

public static final Object LOCK = new Object();

并将您的方法更改为

private void sync_foo() {
    synchronized(LOCK) {
        final Logger log = Logger.getLogger(getClass());
        log.info("start");
        log.info("still alive");
        ...
        log.info("finish");
    }
}

所以调用 sync_foo 的所有对象都将使用相同的锁,而不管它调用的是什么实例。