Нужно ли синхронизировать доступ в конструкторе к общей статической переменной? - PullRequest
3 голосов
/ 01 марта 2012

Я знаю, что конструкторы не могут быть синхронизированы в Java.Означает ли это, что если конструктор изменяет статическую переменную внутри класса и если конструкторы могут вызываться из нескольких потоков, то доступ должен быть синхронизирован, как показано?

public class MyClass {
  private static int count = 0;

  public MyClass() {
    synchronized(MyClass.class) {
      count++;
    }
    ...
  }
}

Ответы [ 3 ]

8 голосов
/ 01 марта 2012

Абсолютно - в конце концов, он обращается к общему ресурсу, возможно, через множество потоков. Лично я бы вместо этого просто использовал AtomicInteger.

public class MyClass {
  private static final AtomicInteger count = new AtomicInteger();

  public MyClass() {
    count.incrementAndGet();
  }
}

Обратите внимание, что теперь мы можем сделать переменную final, так как переменная не меняет значение, и нам больше не нужно синхронизировать все элементы классов в java. util.concurrent.atomic заключается в том, что они могут использоваться атомарно без дополнительной синхронизации.

Даже если вы находитесь в в ситуации, когда вам нужно синхронизировать, я бы не использовал MyClass.class для этого - это ссылка, по которой другой код может решить синхронизироваться, поэтому вы можете ' Я больше не думаю о вашем коде. Я бы написал (опять же, только если по какой-то причине AtomicInteger недостаточно хорош):

public class MyClass {
  private static final Object countLock = new Object();
  private static int count = 0;

  public MyClass() {
    synchronized(countLock) {
      count++;
    }
    ...
  }
}

(В этом случае вы также хотите синхронизироваться на countLock везде, где у вас есть доступ к count, даже только для чтения.)

1 голос
/ 01 марта 2012

Для этого случая я бы рекомендовал использовать AtomicInteger

1 голос
/ 01 марта 2012

Необходима какая-то синхронизация, и это сработало бы, да. Это выполнит то же самое, что и синхронизированный статический метод. Вместо этого вы можете использовать AtomicInteger.

...