Java swingWorker调用的同步方法中断了吗?

Java swingWorker调用的同步方法中断了吗?,java,multithreading,logging,log4j,synchronized,Java,Multithreading,Logging,Log4j,Synchronized,我有一个同步函数,它是从另一个函数中的循环在一个新线程中启动的,并且有许多对它的调用。因此,我: foo(){ new SwingWorker() { @Override public void doInBackground() { sync_foo(); } }.execute(); } catch (IOException e) {

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

foo(){
new SwingWorker() {
                @Override
                public void doInBackground() {
                    sync_foo();
                }
            }.execute();
} catch (IOException e) {
            log.error("", e);
        }
}
sync\u foo
定义为:

private synchronized void sync_foo() {
}
我在
sync\u foo
中放置了一些调试行,以检查它是否如我所期望的那样工作。所以我有:

private synchronized void sync_foo() {
    final Logger log = Logger.getLogger(getClass());
    log.info("start");
    ...
    log.info("finish");
}
这里的记录器是Log4J,我知道它确实是线程安全的。我注意到在日志文件中,有时会有两个后续的“开始”。因此,我在
log.info(“仍然活着”)
的末尾添加了另一行,并不断地将其放在
log.info(“开始”)附近
以查看我是否曾经停止获得双
启动
并始终在这两者之间获得
仍处于活动状态
,但我仍然获得了它,最后我求助于将它放在
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\u foo()
只从
foo()
调用,我没有收到任何异常或错误

因此,问题是:

  • 一般来说,方法本身被中断的可能原因是什么

  • 我知道Swing worker可能有自己处理线程执行的方法。我在上面使用的SwingWorker实际上已被重写,其定义如中所示。此扩展中是否有任何内容可能遗漏相关的异常


    • 同步依赖于共享锁,因此如果您看到多个线程同时调用同步的对象,这意味着它们没有使用同一个锁。听起来像是在不同的对象上调用了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\u foo的所有对象都将使用相同的锁。

      您能否确认每次调用sync\u foo时都是针对同一对象,并且不是每次都创建该对象?请在问题文本中包含相关代码。“我们并不是都能进入pastebin。”内森豪斯肯定。只是我的格式有问题,这让我很恼火。@coder它确实在同一个对象上。实际上,我最初是用一个静态ReentrantLock编写的,没有将例程声明为synchronized,并且得到了一些类似的结果。我采用了很好的旧同步思想来解决这个问题,但它没有。”作为替代方案,我可以在主方法(或另一个合适的位置)中创建一个
      LOCK
      对象,并将它从方法调用传递到方法调用。使用
      static
      是可以避免的,而且代码可以更好地重用。@slartidan:同意,使用static不是最好的,只是在没有更多信息的情况下很难知道该放在哪里。@NathanHughes事实上,我最初写的和你上面写的一样。我使用了一个静态的
      ReentrantLock
      ,得到了类似的结果。这就是为什么我切换到synchronized,认为我可能没有正确理解锁,所以我不认为这是一个多线程问题,看起来线程实际上被中断了。奇怪。在调用
      sync\u foo()
      之前,我在
      foo()
      中放入了两个计数器变量,一个在
      sync\u foo()
      中递增,最后一个在
      sync\u foo()中递增。令我惊讶的是,当所有的通话都快结束时,它们几乎是同步的。但这并不是您在查看日志文件时得到的印象。“开始”比“完成”多得多。就像2:1甚至3:1。所以,看起来logger并没有记录很多
      log.info(“finish”)消息。为什么会这样?顺便说一句,我的
      log.info(“开始”)实际上是
      log.error(“start”)因为我已经配置Intellij以不同的颜色显示它们。从这种行为可以得出什么结论?该记录器对彼此不同步的
      error()
      info()
      有不同的QUE?