2016-11-14 3 views
1

Я пытаюсь подсчитать, сколько экземпляров класса, сгенерированного в течение времени выполнения процесса в многопоточной среде. То, как я делаю это, чтобы увеличить статический счетчик в конструкторе, глядя на это сообщение: How to Count Number of Instances of a ClassПодсчитайте количество экземпляров класса в многопоточной среде?

Таким образом, в многопоточной среде, вот как я определить класс:

class Television { 
     private static volatile int counter = 0; 
     public Television(){ 
      counter ++; 
     } 
} 

Однако , Я не уверен, есть ли потенциальная ошибка с кодом выше, так как я думаю, что конструктор в java не подразумевает синхронизацию и counter++не является атомарным, так что если два потока создают экземпляры одновременно, является ли код как-то ошибкой? но я еще не совсем уверен.

+2

Правильно, есть ошибка, поскольку считывание счетчика и запись в счетчик не выполняются атомарно. Используйте 'AtomicInteger'. –

+0

Используйте атомный счетчик. tutorial/essential/parallelurrency/atomicvars.html –

+0

И, конечно же; один интересный вопрос: почему вы хотите это сделать? Какую проблему вы намерены решить, зная о количестве экземпляров? – GhostCat

ответ

3

Там есть ошибка в этом коде (в частности, состояние гонки), потому что чтение счетчика и запись в счетчик не атомарно выполняется.

Другими словами, два потока могут считывать одно и то же значение counter, увеличивать это значение, а затем записывать то же значение обратно в переменную.

Thread 1 Thread 2 
======== ======== 

Read 0 
      Read 0 
Increment 
      Increment 
Write 1 
      Write 1 

Таким образом, значение будет 1, а не 2, впоследствии.

Вместо этого использовать AtomicInteger и AtomicInteger.incrementAndGet().

1

Как counter++ не является атомарным, вы можете заменить его на JDK AtomicInteger, который является потокобезопасным.

Вы можете использовать getAndIncrement() метод AtomicInteger «ы, как показано ниже:

class Television { 
     private static final AtomicInteger counter = new AtomicInteger(); 
     public Television(){ 
      counter.getAndIncrement(); 
     } 
} 

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

Вы можете посмотреть here

+0

Не нужно указывать, что AtomicInteger нестабилен. Под капотом он использует переменную volatile для сохранения значения. – jgitter

+0

У меня получилось, спасибо – developer

+0

Гораздо важнее отметить его «финал». –

1

Есть два способа здесь, чтобы обойти лежащий в основе «++ на ИНТ» не будучи атомарные операции:

А), как другие предложили, использовать AtomicInteger

B) ввести общий ЗАМОК, что все ctors может использоваться для синхронизации; например:

private final static Object LOCK = new Object(); 

public Television() { 
    synchronized (LOCK) { 
    counter++; 
    } 
Смежные вопросы