동기화 된 메서드가 다른 동기화 된 메서드를 호출하는 경우 스레드로부터 안전합니까?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
동기화 된 메서드가 다른 동기화 된 메서드를 호출하는 경우 스레드로부터 안전합니까?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
답변:
예, 메소드를으로 표시 synchronized
하면 실제로 다음을 수행하는 것입니다.
void method1() {
synchronized (this) {
method2()
}
}
void method2() {
synchronized (this) {
}
}
스레드 호출이 method1에서 method2로 들어가면 잠금을 this
이미 한 다음 통과 할 수 .
스레드가 method1 또는 method2로 직접 들어가면 잠금 ( this
)을 얻을 수있을 때까지 차단 된 다음 들어갑니다.
James Black이 주석에서 언급했듯이 메서드 본문 내에서 수행하는 작업에 대해 알고 있어야합니다.
private final List<T> data = new ArrayList<T>();
public synchronized void method1() {
for (T item : data) {
// ..
}
}
public void method3() {
data.clear();
}
비 동기화되어 스레드 B가에서 작업하는 동안 스레드 A가 호출 할 수 ConcurrentModificationException
있기 때문에 미래 에 a 를 보고 있기 때문에 갑자기 스레드로부터 안전하지 않습니다 .method3
method1
method3
안전하지 않은 스레딩 작업을 보여 주지만 재진입 동기화에 대해 주목하고 있습니다.
Java Tutorials 사이트 http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html에서
동일한 개체에서 동기화 된 메서드를 두 번 호출하는 것은 인터리브 할 수 없습니다. 한 스레드가 개체에 대해 동기화 된 메서드를 실행할 때 첫 번째 스레드가 개체에 대해 완료 될 때까지 동일한 개체 블록에 대해 동기화 된 메서드를 호출하는 다른 모든 스레드 (실행 일시 중지)입니다.
동기화 된 메서드가 종료되면 동일한 개체에 대한 동기화 된 메서드의 후속 호출과 사전 발생 관계를 자동으로 설정합니다. 이렇게하면 개체의 상태 변경 사항이 모든 스레드에 표시됩니다.
따라서 Java는 두 스레드가 동일한 메서드를 실행하는 경우 메서드가 동시에 실행되지 않고 차례로 실행되도록합니다.
하지만 Liveness 문제를 알고 있어야합니다. http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
또한 불필요하게 잠그고 있는지 여부에 관계없이 전체 객체를 잠그는 코드에서 this 를 사용 하여 객체가 하나의 변수에 대한 동기화 액세스 만 필요하면 해당 변수를 잠 가야합니다.
synchronized (this.someVar)
참조가에서 유지되는 객체를보고 있다고 말합니다 someVar
. 구별은 매우 중요합니다.