[java] Java에서 클래스의 다른 인스턴스를 실행하는 스레드간에 정적 변수를 동기화하는 방법은 무엇입니까?

나는 synchronize메서드 앞에 키워드 해당 개체에 동기화가 발생한다는 있습니다. 즉, 개체의 동일한 인스턴스를 실행하는 2 개의 스레드가 동기화됩니다.

그러나 동기화가 개체 수준에 있기 때문에 개체의 다른 인스턴스를 실행하는 2 개의 스레드는 동기화되지 않습니다. 메서드에 의해 호출되는 Java 클래스에 정적 변수가있는 경우 클래스 인스턴스간에 동기화되기를 원합니다. 두 인스턴스는 두 개의 서로 다른 스레드에서 실행됩니다.

다음과 같은 방법으로 동기화 할 수 있습니까?

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입니까?



답변

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

  1. 동기화 된 정적 방법을 사용하십시오. 이것은 클래스 객체에서 동기화됩니다.

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

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

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

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


답변

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

public class Test {

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

    public void foo() {
        count.incrementAndGet();
    }
}


답변

그래, 사실이야.

클래스의 두 인스턴스를 만드는 경우

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

그런 다음 t1.foo 및 t2.foo는 모두 동일한 정적 개체에서 동기화되므로 서로를 차단합니다.


답변

클래스를 통해 코드를 동기화 할 수 있습니다. 그게 가장 간단합니다.

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

이 답변이 유용하기를 바랍니다.


답변

ReentrantLock 을 사용 하여 정적 변수에 대한 동기화를 수행 할 수도 있습니다 .

public class Test {

    private static int count = 0;
    private static final ReentrantLock reentrantLock = new ReentrantLock();
    public void foo() {
        reentrantLock.lock();
        count = count + 1;
        reentrantLock.unlock();
    }
}


답변