问题描述
我有一个同步函数,该函数是从另一个函数的循环中在新线程中启动的,并且有很多对其的调用。 所以我有:
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("still alive")
附近添加了另一行,并使其越来越接近log.info("start");
看看我是否曾经停止过两次重新starts
并且始终在两次之间still alive
,但是我仍然在继续,最后我将其放在log.info("start");
的下一行上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()
并且没有任何异常或错误。
所以问题是:
通常,方法自身中断的可能原因是什么?
我知道Swing worker可能有其自己的方式来处理线程执行。 我上面使用的SwingWorker实际上已被覆盖,其定义如此 。 此扩展程序中是否有任何东西可以错过相关的例外?
1楼
同步取决于共享锁,因此,如果您看到多个线程正在调用并发同步的内容的行为,则意味着它们没有使用相同的锁。
听起来好像在不同的对象上调用了sync_foo。
在方法上使用synchronized
意味着对象实例上的监视器是由要进入该方法的线程获取的,因此,如果在不同对象上调用该方法,则不会有共享锁,也不会阻止线程在一个对象上进入方法而另一个线程正在另一个对象上执行该方法。
您可以像这样进行类级锁定:
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的对象都将使用相同的锁。