Java에서 클래스의 서로 다른 인스턴스를 실행하는 스레드 간에 정적 변수를 동기화하는 방법은 무엇인가요?

메서드 앞에 '동기화' 키워드를 사용하면 해당 객체가 동기화된다는 것을 알고 있습니다. 즉, 객체의 동일한 인스턴스를 실행하는 두 개의 스레드가 동기화됩니다.

그러나 동기화는 객체 수준에서 이루어지기 때문에 객체의 다른 인스턴스를 실행하는 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 키워드를 사용하고 있으므로 이제 정적 변수 countTest 클래스의 인스턴스 간에 동기화되는 것이 맞나요?

질문에 대한 의견 (2)
해결책

정적 변수에 대한 액세스를 동기화하는 방법에는 여러 가지가 있습니다.

  1. 동기화된 정적 메서드를 사용합니다. 이는 클래스 객체에서 동기화됩니다.

     public class Test {
         private static int count = 0;
    
         공용 정적 동기화 void incrementCount() {
             count++;
         }
     }
  2. 클래스 객체에서 명시적으로 동기화합니다.

     public class Test {
         공용 정적 int count = 0;
    
         public void incrementCount() {
             동기화 (Test.class) {
                 count++;
             }
         }
     }
  3. 다른 정적 객체에서 동기화합니다.

     public class Test {
         private static int count = 0;
         비공개 정적 최종 객체 countLock = 새로운 객체();
    
         public void incrementCount() {
             동기화 (countLock) {
                 count++;
             }
         }
     }

잠금 객체가 클래스 외부에 노출되지 않기 때문에 대부분의 경우 방법 3이 가장 좋습니다.

해설 (5)

단순히 카운터를 공유하는 경우, AtomicInteger 또는 java.util.concurrent.atomic 패키지의 다른 적절한 클래스를 사용하는 것이 좋습니다:

public class Test {

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

    public void foo() {  
        count.incrementAndGet();
    }  
}
해설 (1)

네, 사실입니다.

클래스의 인스턴스를 두 개 생성하는 경우

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

그러면 t1.foo와 t2.foo는 모두 동일한 정적 객체에서 동기화되므로 서로를 차단합니다.

해설 (1)

클래스 코드에 대한 동기화할 수 있습니다. 가장 단순한 일 것이라고 말했다.

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

이 질문에 쉽게 찾을 수 있다.

해설 (2)