我有一个同步函数,它是从另一个函数的循环中在新线程中启动的,并且有很多调用它。所以我有:
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,据我所知,它确实是线程安全的。我注意到在日志文件中有时有两个后续的“开始”。因此,我在末尾附近添加了另一行 log.info("stillalicious")
并不断将其越来越靠近 log.info("start");
到看看我是否曾经停止获得双 starts
并且总是在两者之间获得 stilllive
,但我仍然得到它,最后我把它放在下一行 log.info("开始");
:
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()
调用,并且我没有收到任何类型的异常或错误。
所以问题是:
一般来说,方法被自身中断的可能原因有哪些?
我知道 Swing Worker 可能有自己的处理线程执行的方法。我上面使用的 SwingWorker 实际上已被重写,其定义如 here 中所示。 。此扩展中是否有任何内容可能导致错过相关异常?
最佳答案
同步取决于共享锁,因此如果您看到多个线程同时调用同步的内容的行为,则意味着它们没有使用相同的锁。听起来好像在不同的对象上调用了sync_foo。在方法上使用同步意味着对象实例上的监视器由想要进入该方法的线程获取,因此如果在不同对象上调用该方法,则不会有共享锁,也不会阻止线程当另一个线程正在另一个对象上执行该方法时,进入一个对象上的方法。
你可以像这样创建一个类级锁:
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的所有对象都将使用相同的锁。
关于java - swingWorker调用的synchronized方法被中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31480100/