Java 跳出同步块?

Java 跳出同步块?,java,synchronized,Java,Synchronized,我有这个: synchronized(c){ if (!items.hasNext() && (c.getFinishedCount() == c.getStartedCount())) { f.done(null, results); return; } if(c.isBelowCapacity()){ RunMap(items,m,results,c,s,f); } } 但最终,当我调用RunMap()或f

我有这个:

synchronized(c){
   if (!items.hasNext() && (c.getFinishedCount() == c.getStartedCount())) {
      f.done(null, results);
      return;
    }

    if(c.isBelowCapacity()){
      RunMap(items,m,results,c,s,f);
    }
}
但最终,当我调用
RunMap()
f.done()
时,我不需要在c上同步,我只需要在执行条件检查/if语句时在c上同步


我应该让c上的方法同步,然后去掉同步块吗


我是否应该让c上的方法同步,然后去掉 同步块

不,更好的方法是在synchronized块内进行检查,然后稍后执行其余工作:

boolean bFDone = false;
boolean bRunMap = false;

synchronized (c) {
    bFDone = !items.hasNext() && (c.getFinishedCount() == c.getStartedCount());
    bRunMap = !bFDone && c.isBelowCapacity();
}

if (bFDone) {
    f.done(null, results);
} else if (bRunMap) {
    RunMap(items,m,results,c,s,f);
}
这个版本的最大优点是,所有的易失性代码实际上都是同步的,而其余的(可能很慢的)事情会在以后发生


正如在对这个答案的评论中正确提到的,只有在您最初的假设是正确的,即整个块不需要同步的情况下,这才是正确的。如果您需要立即对条件作出反应,那么实际上需要(完全)同步块。

使
c
的方法同步可能是个坏主意。首先,这意味着无论何时调用它们,无论上下文如何,它们都将同步,这可能不是您的意思。其次,它无助于原子化地解决条件
!items.hasNext()
c.getFinishedCount()==c.getStartedCount()

一个选项是初始化
synchronized
块内的
boolean
变量,然后在块外执行相关调用:

final boolean isDone;
synchronized(c) {
    isDone = !items.hasNext() && (c.getFinishedCount() == c.getStartedCount());
}

if (isDone) {
    f.done(null, results);
    return;
}

final boolean isBelowCapacity;
synchronized(c) {
    isBelowCapacity =  c.isBelowCapacity();
}

if (isBelowCapacity) {
    RunMap(items,m,results,c,s,f);
}

“我应该让c上的方法同步吗”您可以,但是您将单独同步,这可能不是您想要的。然而,最大的缺点是,导致您选择
f.done
RunMap
的条件在您调用它们时可能不正确。好的策略,但请注意,OP必须确保这是他/她想要的。如果
runMap()。如果它读取的是
c
,那么当它不再有效时,它可能正在读取
c
。这是真的,但根据OP,其余的代码不需要同步,因此调用应该能够承受。否则OPs的假设是错误的,即整个代码不需要同步。@TreffnonX是的,我认为最好警告OPs其含义是什么,以防他或她之前可能没有考虑到。是的,我特别欣赏这一观察“首先,这意味着无论何时调用它们,无论上下文如何,它们都将同步”b/c我在发布问题时就是这么想的