为了账号安全,请及时绑定邮箱和手机立即绑定

打破同步块?

打破同步块?

米脂 2022-06-15 09:47:01
我有这个: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()orf.done()时我不需要在 c 上同步,我只需要在执行条件检查 / if 语句时在 c 上同步。我应该只使 c 上的方法同步,然后摆脱同步块吗?
查看完整描述

2 回答

?
眼眸繁星

TA贡献1873条经验 获得超9个赞

我应该只使 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);

}

这个版本的最大优势是,所有易失性代码实际上都是同步的,其余(可能很慢)的东西会在以后发生。


正如在这个答案的评论中正确提到的那样,如果您的初始假设是正确的,那么这只会正常工作,即整个块不需要同步。如果您需要立即对条件做出反应,那么该块实际上需要(完全)同步。


查看完整回答
反对 回复 2022-06-15
?
www说

TA贡献1775条经验 获得超8个赞

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

}


查看完整回答
反对 回复 2022-06-15
  • 2 回答
  • 0 关注
  • 79 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信