Как синхронизировать статическую переменную среди потоков, выполняющих различные экземпляры класса в Java?

Я знаю то использование synchronize ключевое слово перед методом приносит синхронизацию к тому объекту. Таким образом, будут синхронизироваться 2 потока, выполняющие тот же экземпляр объекта.

Однако, так как синхронизация на уровне объектов, 2 потока, выполняющие различные экземпляры объекта, не будут синхронизироваться. Если у нас есть статическая переменная в классе Java, который называет метод, мы хотели бы, чтобы он синхронизировался через экземпляры класса. Эти два экземпляра работают в 2 различных потоках.

Мы можем достигнуть синхронизации следующим образом?

public class Test  
{  
   private static int count = 0;  
   private static final Object lock= new Object();    
   public synchronized void foo() 
  {  
      synchronized(lock)
     {  
         count++;  
     }  
  }  
}

Действительно ли это верно это, так как мы определили объект lock это статично, и мы используем ключевое слово synchronized для той блокировки, статической переменной count теперь синхронизируется через экземпляры класса Test?

119
задан Shepmaster 26 April 2018 в 21:56
поделиться

3 ответа

Существует несколько способов синхронизации доступа к статической переменной.

  1. Используйте синхронный статический метод. Это синхронизирует на объекте класса.

     Тест общего класса {
      Частный статический int count = 0;
    
      Общественная статическая синхронизированная недейственная инкрементCount () {
      Count ++;
      }
     }
     
  2. Явно синхронизируется на объекте класса.

     Тест общего класса {
      Частный статический int count = 0;
    
      общедоступная недейственная инкрементCount () {
      синхронизирован (test.class) {
      Count ++;
      }
      }
     }
     
  3. Синхронизация на каком-то другом статическом объекте.

     Тест общего класса {
      Частный статический int count = 0;
      Частный статический конечный объект CountLock = новый объект ();
    
      общедоступная недейственная инкрементCount () {
      синхронизирован (CountLock) {
      Count ++;
      }
      }
     }
     

Метод 3 - лучшее во многих случаях, потому что объект блокировки не выставлен вне вашего класса.

191
ответ дан 24 November 2019 в 01:48
поделиться

Да верно.

Если вы создаете два экземпляра вашего класса

Test t1 = new Test();
Test t2 = new Test();

, то T1.foo и T2.foo оба синхронизируются на одном статическом объекте и, следовательно, блокируют друг друга.

4
ответ дан 24 November 2019 в 01:48
поделиться

Если вы просто делитесь счетчиком, подумайте об использовании AtomicInteger или другого подходящего класса из пакета java.util.concurrent.atomic:

public class Test {

    private final static AtomicInteger count = new AtomicInteger(0); 

    public void foo() {  
        count.incrementAndGet();
    }  
}
64
ответ дан 24 November 2019 в 01:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: