突破同步块?

时间:2019-02-11 07:19:39

标签: 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.done()时,不需要在c上进行同步,而在执行条件检查/ if语句时,只需要在c上进行同步即可。

我是否应该使c上的方法同步,然后摆脱同步块?

2 个答案:

答案 0 :(得分:4)

  

我应该使c上的方法同步,然后摆脱   同步块?

否,更好的方法是在同步块内进行检查,然后稍后再进行其余工作:

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);
}

此版本的最大优点是,所有易失性代码实际上都已同步,而其余(可能很慢)的东西会稍后发生。

正如在此答案的注释中正确提到的那样,如果您最初的假设是正确的,那么只有在整个块不需要同步的情况下,这才可以正常工作。如果您需要立即对条件做出反应,则实际上需要完全同步该块。

答案 1 :(得分:2)

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

一种选择是初始化boolean块内的synchronized变量,然后在它们之外执行相关调用:

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);
}