Что является более эффективным и почему? - PullRequest
2 голосов
/ 10 ноября 2010

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

public synchronized void addName(String name) 
{
       lastName = name;
       nameCount++;
       nameList.add(name);
}

или

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
        nameList.add(name);
    }

}

Также, каков рекомендуемый способ обработки параллелизма:

  1. с использованием java.util.concurrent пакета
  2. с использованием вышеупомянутых методов низкого уровня
  3. с использованием Job или UIJob API (при работе в среде Eclipse PDE)

Спасибо

Ответы [ 6 ]

5 голосов
/ 10 ноября 2010

какой оптимизирован (как при обработке и сгенерированном байт-коде)

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

Фрагмент из статьи:

Когда JVM выполняет синхронизированный метод, исполняющий поток идентифицирует, что структура method_info метода имеет установленный флаг ACC_SYNCHRONIZED, затем онавтоматически получает блокировку объекта, вызывает метод и снимает блокировку.Если возникает исключение, поток автоматически снимает блокировку.

С другой стороны, синхронизация блока метода обходит встроенную поддержку JVM для получения блокировки объекта и обработки исключений и требует, чтобы функциональность была явнонаписано в байтовом коде.Если вы прочитаете байт-код для метода с синхронизированным блоком, вы увидите более десятка дополнительных операций для управления этой функцией.В листинге 1 показаны вызовы для генерации как синхронизированного метода, так и синхронизированного блока:

Отредактировано для адресации первого комментария

Чтобы дать кредит другим SOers, вотхорошее обсуждение того, почему можно использовать синхронизацию.блок.Я уверен, что вы сможете найти более интересные обсуждения, если будете искать по кругу:)

Есть ли преимущество в использовании синхронизированного метода вместо синхронизированного блока?

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

5 голосов
/ 10 ноября 2010
  • Ваши обновленные две части кода семантически идентичны.Однако использование синхронизированного блока, как во втором фрагменте, дает вам больший контроль, поскольку вы можете синхронизировать другой объект или даже не синхронизировать части метода, которые не должны быть.
  • Использование java.util.concurrent очень предпочтительнее использования примитивов синхронизации везде, где это возможно, поскольку оно позволяет работать на более высоком уровне абстракции и использовать код, который был написан очень опытными людьми и интенсивно проверен.
  • Если выработая в eclipse PDE, использование его API, скорее всего, предпочтительнее, так как оно связано с остальной частью платформы.
2 голосов
/ 10 ноября 2010

Это совершенно не имеет значения с любой точки зрения эффективности.

Смысл наличия блоков в том, что вы можете указать свой собственный замок.Вы можете выбрать блокировку, инкапсулированную в объекте, в отличие от использования this, в результате чего у вас будет больше контроля над тем, кто может получить блокировку (поскольку вы можете сделать эту блокировку недоступной извне вашего объекта).

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

Ограничение доступа к блокировке дает вам огромный выигрыш в разрешимости, гораздо полезнее иметь такую ​​уверенность, чем где-то сбрить байт-код.

1 голос
/ 11 ноября 2010

Вы можете снять все блокировки:

class Names {
  AtomicReference<Node> names = new AtomicReference<Node>();

  public void addName(final String name) {
    Node old = names.get();
    while (!names.compareAndSet(old, new Node(old, name))) {
      old = names.get();
    }
  }

  public String getName() {
    final Node node = names.get();
    return (node == null) ? null : node.name;
  }

  static class Node {
    final Node parent;
    final String name;

    Node(final Node parent, final String name) {
      this.parent = parent;
      this.name = name;
    }

    int count() {
      int count = 0;
      Node p = parent;
      while (p != null) {
        count++;
        p = p.parent;
      }
      return count;
    }
  }
}

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

1 голос
/ 10 ноября 2010

Я знаю, что это может быть примером, но если вы планируете писать такой код - подумайте еще раз.

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

  • Если вам действительно нужно, чтобы это был код, выполняющийся в нескольких потоках, я бы включил nameList в синхронизированный список с использованием Collections.synchronizedList.
  • Фамилия должна быть получателем, и она может выбрать последний элемент в списке.
  • Имя nameCount должно быть размером списка.

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

0 голосов
/ 10 ноября 2010

Невозможно сказать, поскольку два фрагмента кода не эквивалентны.

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

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