나는 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
입니까?
답변
정적 변수에 대한 액세스를 동기화하는 방법에는 여러 가지가 있습니다.
-
동기화 된 정적 방법을 사용하십시오. 이것은 클래스 객체에서 동기화됩니다.
public class Test { private static int count = 0; public static synchronized void incrementCount() { count++; } }
-
클래스 개체에서 명시 적으로 동기화합니다.
public class Test { private static int count = 0; public void incrementCount() { synchronized (Test.class) { count++; } } }
-
다른 정적 개체에서 동기화합니다.
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();
}
}