Синхронизированные методы - PullRequest
10 голосов
/ 30 марта 2011

Если у меня есть синхронизированный публичный метод и приватный метод:

public synchronized void doSomething() {
    doSomethingElse()
}

private void doSomethingElse() {
}

Нужно ли синхронизировать приватный метод?

Ответы [ 9 ]

15 голосов
/ 30 марта 2011

Это зависит от:

  • Если doSomethingElse безопасно для одновременного вызова, тогда вам не нужно synchronized.
  • Если это не так, то ответ зависит от того, откуда он вызывается:
    • Если он вызывается только из других synchronized методов, то он не обязательно должен быть synchronized (но его пометка не нанесет вреда);
    • Если он может быть вызван из методов, которые сами не являются synchronized, тогда он должен быть synchronized.
5 голосов
/ 30 марта 2011

Это зависит от того, что вы делаете.Вам необходимо обеспечить последовательный доступ к doSomethingElse()?

Если это так, и единственное, что вызывает doSomethingElse(), это doSomething(), то нет, вам не нужно синхронизироваться.Но если какой-то другой метод может вызвать doSomethingElse(), тогда да, вы должны также синхронизировать его.

4 голосов
/ 30 марта 2011

NO: , если единственный способ doSomethingElse() вызывается через другой метод, который синхронизирован.

Возможно ДА: Если вы вызываете doSomethingElse() каким-либо другим способом, через метод, который не синхронизирован, и вам необходимо защитить его от одновременного доступа.

2 голосов
/ 31 марта 2011

Это намерение аннотации @GuardedBy. Если вы ожидаете, что блокировка должна удерживаться при вызове этого метода, пометьте его этим и именем блокировки (в примере это будет:

@GuardedBy("this") private void doSomethingElse() {…}

Затем вы можете проверить, что инвариант верен с FindBugs.

Вы также можете использовать other net.jcip.annotations для описания безопасности потока или его отсутствия, а FindBugs также проверит эти предположения. Конечно, книге также нужна вилка.

1 голос
/ 30 марта 2011

Все методы, вызываемые из синхронизированного метода (или из блока synchronized), выполняются, пока они еще синхронизированы. Вам не нужно отдельно синхронизировать закрытый метод, если он вызывается только из синхронизированных методов.

0 голосов
/ 05 октября 2016

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

Внутренние блокировки являются реентерабельными, добавление синхронизированного ключевого слова в закрытый метод не причинит никакого вреда.

Помещение кода в закрытый метод позволяет его вызывать другими методами, поэтому имеет смысл синхронизировать закрытый метод в случае, если в будущем он будет вызван из другого метода, который иначе не требует синхронизации.

0 голосов
/ 30 марта 2011

Хотя то, что вы сделали, хорошо, на мой взгляд, синхронизация должна выполняться с минимально возможной степенью детализации.Что бы предложить синхронизировать реальную частную функцию.В настоящее время вы предполагаете, что никакая другая функция в классе не будет вызывать частную функцию независимо.Это может быть не так в будущем.

0 голосов
/ 30 марта 2011

Лично я не люблю синхронизированные методы.Я предпочитаю синхронизироваться с какой-нибудь блокируемой переменной, например:

private final Object lock = new Object();

public void doSomething() {
  synchronized(lock) {
    // Do some safely
    doSomethingElse();
  }
  // Do some work un-safely
}

private void doSomethingElse() {
  // Do some work safely because still in lock above
  // ...
}
0 голосов
/ 30 марта 2011

Если вы синхронизируете блок кода, то все, что вызывается из этого блока кода (в том же потоке), все еще содержит первоначальную блокировку. Таким образом, doSomethingElse все еще является частью синхронизированного блока, когда он вызывается из doSomething.

Если вы сделали:

public synchronized void doSomething() {
  new Thread() {
    public void run() {
      doSomethingElse();
    }
  }.start();
}
private void doSomethingElse() {
}

Тогда doSomethingElse будет не иметь блокировку, полученную doSomething.

Также избегайте синхронизированных методов, так как это раскрывает детали реализации вашей политики параллелизма. См. Этот вопрос о синхронизированных (это) / синхронизированных методах: Избегать синхронизированных (это) в Java?

Если doSomethingElse необходимо синхронизировать, независимо от того, вызывается он из doSomething или нет, синхронизировать doSomethingElse не помешает, так как синхронизированные блокировки являются входящими (т. Е. Если поток уже имеет заблокировать объект, он может снова получить блокировку).

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