Вырваться из синхронизированного блока? - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть это:

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

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

, но в конечном итоге мне не нужно синхронизироваться на c, когда я звоню RunMap() или f.done(), мне просто нужно синхронизироваться на c, когда я делаюусловные проверки / операторы if.

Стоит ли просто синхронизировать методы на c, а затем избавиться от синхронизированного блока?

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Синхронизация методов 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);
}
0 голосов
/ 11 февраля 2019

Должен ли я просто синхронизировать методы на 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);
}

Большим преимуществом этой версии является то, что весь энергозависимый код фактически синхронизирован, а остальные (потенциально медленные) вещи происходят позже.

Как правильно указано в комментариях к этому ответу, это работает правильно, только если ваше первоначальное предположение верно, что весь блок не нуждается в синхронизации.Если вам нужно немедленно отреагировать на условия, тогда блок должен быть фактически синхронизирован (полностью).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...