Break out of synchronized block?

user5047085 :

I have this:

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

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

but ultimately I don't need to be synchronized on c when I call RunMap() or f.done(), I just need to be synchronized on c when I do the conditional checks / if statements.

Should I just make the methods on c synchronized, and then get rid of the synchronized block?

TreffnonX :

Should I just make the methods on c synchronized, and then get rid of the synchronized block?

No, the better way is to make the checks within the synchronized block, and then do the rest of the work later:

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

The big advantage of this version is, that all the volatile code is actually synchronized, and the rest (potentially slow) stuff happens later.

As mentioned correctly in the comments to this answer, this only works correctly, if your initial assumption is correct, that the entire block does not need synchronization. If you need to react to the conditions immediately, then the block needs to be in fact synchronized (entirely).

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=75785&siteId=1