[java] Java 동기화 정적 메소드 : 오브젝트 또는 클래스 잠금

자바 문서는 말합니다 :

동일한 오브젝트에서 동기화 된 메소드를 두 번 호출하여 인터리브 할 수 없습니다.

정적 메소드의 의미는 무엇입니까? 정적 메서드에는 연결된 개체가 없으므로 동기화 된 키워드가 개체 대신 클래스에서 잠깁니까?



답변

정적 메서드에는 연결된 개체가 없으므로 동기화 된 키워드가 개체 대신 클래스에서 잠깁니까?

예. 🙂


답변

Oscar의 답변에 약간의 세부 사항을 추가하기 위해 Java 언어 사양의 관련 섹션은 8.4.3.6, ‘동기화 방법’입니다 .

동기화 된 방법은 모니터 가 실행되기 전에 ( §17.1 ) 획득합니다 . 클래스 (정적) 메소드의 경우 메소드 클래스의 클래스 오브젝트와 연관된 모니터가 사용됩니다. 인스턴스 메소드의 경우, 이와 연관된 모니터 (메소드가 호출 된 오브젝트)가 사용됩니다.


답변

주의해야 할 한 가지 점은 (여러 프로그래머가 일반적으로 해당 트랩에 속함) 동기화 된 정적 메소드와 동기화 된 비 정적 메소드 사이에 링크가 없다는 것입니다.

class A {
    static synchronized f() {...}
    synchronized g() {...}
}

본관:

A a = new A();

실 1 :

A.f();

실 2 :

a.g();

f ()와 g ()는 서로 동기화되지 않으므로 완전히 동시에 실행할 수 있습니다.


답변

다음과 같이 g ()를 구현하지 않는 한 :

g() {
    synchronized(getClass()) {
        ...
    }
}

이 패턴은 객체의 다른 인스턴스간에 상호 배제를 구현하려는 경우에도 유용합니다 (예 : 외부 리소스에 액세스 할 때 필요함).


답변

내장 잠금 및 동기화 에 대한 Oracle 설명서 페이지를 살펴보십시오

정적 메소드가 오브젝트가 아닌 클래스와 연관되어 있기 때문에 정적 동기화 메소드가 호출 될 때 어떤 일이 발생하는지 궁금 할 것입니다. 이 경우 스레드는 class와 연관된 Class 객체에 대한 고유 잠금을 획득합니다 . 따라서 클래스의 정적 필드에 대한 액세스는 클래스의 모든 인스턴스에 대한 잠금과 다른 잠금에 의해 제어됩니다 .


답변

정적 메서드에는 관련 개체도 있습니다. JDK 툴킷의 Class.class 파일에 속합니다. .class 파일이 램에로드되면 Class.class는 템플릿 객체라는 파일의 인스턴스를 만듭니다.

예 :-기존 고객 클래스에서 객체를 만들려고 할 때

Customer c = new Customer();

Customer.class는 RAM으로로드됩니다. 이때 JDK 툴킷의 Class.class는 Template 객체라는 객체를 생성하고 해당 Customer.class를 해당 템플릿 객체에로드합니다. 해당 Customer.class의 정적 멤버는 해당 템플릿 객체의 속성과 메소드가됩니다.

따라서 정적 메소드 또는 속성에도 객체가 있습니다


답변

아래 예제는 클래스와 객체 잠금을 더 명확하게 보여줍니다. 아래 예제는 다른 사람들에게도 도움이되기를 바랍니다. 🙂

예를 들어 아래의 메소드 중 하나는 acquire 클래스와 다른 acquire 객체 잠금입니다.

public class MultiThread {

    public static synchronized void staticLock() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }

    public synchronized void objLock() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }
}

이제 우리는 다음과 같은 시나리오를 가질 수 있습니다.

  1. 동일한 객체를 사용하는 스레드 가 objLock OR staticLock 메소드에 동시에 액세스하려고 할 때 (즉, 두 스레드가 동일한 메소드에 액세스하려고 시도하는 경우)

    Thread-0 0
    Thread-0 1
    Thread-0 2
    Thread-0 3
    Thread-0 4
    Thread-1 0
    Thread-1 1
    Thread-1 2
    Thread-1 3
    Thread-1 4
  2. 사용하여 스레드 때 동일한 개체 에 액세스하려고 staticLockobjLock방법 동시에 (시도는 다른 방법을 접근)

    Thread-0 0
    Thread-1 0
    Thread-0 1
    Thread-1 1
    Thread-0 2
    Thread-1 2
    Thread-1 3
    Thread-0 3
    Thread-0 4
    Thread-1 4
  3. 다른 객체를 사용하는 스레드 가 staticLock메소드 에 액세스하려고 할 때

    Thread-0 0
    Thread-0 1
    Thread-0 2
    Thread-0 3
    Thread-0 4
    Thread-1 0
    Thread-1 1
    Thread-1 2
    Thread-1 3
    Thread-1 4
  4. 다른 객체를 사용하는 스레드 가 objLock메소드 에 액세스하려고 할 때

    Thread-0 0
    Thread-1 0
    Thread-0 1
    Thread-1 1
    Thread-0 2
    Thread-1 2
    Thread-1 3
    Thread-0 3
    Thread-0 4
    Thread-1 4