문제
아래 코드의 예상되는 출력 값과 그 이유를 설명하시오.
public class ThreadTest {
public synchronized static void main(String args[]) {
Thread thread = new Thread() {
public void run() {
pong();
}
};
thread.start();
System.out.println("PING");
}
public synchronized static void pong() {
System.out.println("PONG");
}
}
동기화에 관한 중요 사항 (Important Points Regarding Synchronization)
object level
에Method
에만 해당된다.- Method 또는 Block이 동기화된 경우 실행을 시작하려면
object-level lock
이 필요하다.- 동기화(Synchronization)는
deadlock
의 유일한 이유이기 때문에 Java에서 가장 위험한 단어이다.- 필요할 때
synchronized
키워드를 사용하고synchronized block
을 사용
Static Synchronization
- 동기화된 메서드(
synchronized method
)는 순서가 지정된 출력을 가져오는 동작을 잃을 수 있습니다.- 클래스의 객체가 더 많을 경우 특정 인스턴스의 잠금(
lock
)만 획득합니다.- 동기화된 동작을 유지하려면
Static Synchronization
으로 달성할 수 있는instance-level lock
이 아닌class-level lock
이 필요합니다.
클래스가 synchronized
와 static synchronized
메서드 둘 다 가지고 있는 경우 그것들은 서로 다른 lock
을 요구하기 때문에 병렬로 실행 할 수 있다.
아래 그림은 6개의 쓰레드가 있고, 실행 순서는 아래와 같다.
메소드의 완전한 선언은 다음과 같습니다:
method1: public static synchronized void method1()
method2: public static synchronized void method2()
method3: public static void method3()
method4: public synchronized int method4()
method5: public String method5()
t1.method1()
은 Manager 클래스의 class level lock
을 획득하면서 실행을 시작합니다.t2.method2()
는 static synchronized
메서드이므로 실행 시작 시간을 기다립니다. t1이 이미 class level lock
을 획득했기 때문에 class level lock
이 필요합니다. t2는 t1 실행까지 기다려야 합니다.t3.method2()
는 class level lock
이 필요합니다. 그래서 t1이 잠금을 해제할 때까지 기다려야 합니다.t4.method3()
은 lock
이 필요 없는 static
메서드이므로 실행을 시작합니다.t5.method4()
는 인스턴스 메서드 또는 일반 수준의 sychronized
메서드로 실행을 시작하고 object level lock
이 필요하므로 object level lock
을 얻습니다.t6.method5()
는 인스턴스 메서드 또는 일반 메서드이므로 실행을 시작합니다.synchronized | static synchronized |
---|---|
object-level lock | class-level lock |
메서드를 static으로 선언할 필요는 없다. | 메서드를 static으로 선언해야 한다. |
정기적으로 사용해야 한다. | 정기적으로 사용되지 않는다. |
각 object에 대해 다른 인스턴스가 생성된다. | 전체 프로그램에 대해 하나의 인스턴스이다. |