source

Java 8 인터페이스 방식에서 "동기화"가 허용되지 않는 이유는 무엇입니까?

factcode 2022. 8. 31. 22:32
반응형

Java 8 인터페이스 방식에서 "동기화"가 허용되지 않는 이유는 무엇입니까?

Java 8에서는 다음과 같이 간단하게 쓸 수 있습니다.

interface Interface1 {
    default void method1() {
        synchronized (this) {
            // Something
        }
    }

    static void method2() {
        synchronized (Interface1.class) {
            // Something
        }
    }
}

클래스에서도 사용할 수 있는 완전한 동기화 시멘틱스를 얻을 수 있습니다.저는 '아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아.synchronized다음 중 하나:

interface Interface2 {
    default synchronized void method1() {
        //  ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
    }

    static synchronized void method2() {
        // ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
    }
}

2개의 동작한다고 할 수 .단, 2개의 인터페이스는 2개의 인터페이스로 합니다.Interface2계약을 맺다method1() 등에 대하여method2()더, 조금 더 강하게, 조금 더 강하게.Interface1도 있죠. 물론, 우리는 그렇게 주장할 수도 있습니다.default구현은 구체적인 구현 상태에 대해 어떠한 가정도 하지 않아야 합니다. 또는 그러한 키워드가 단순히 그 비중을 차지하지 않을 것입니다.

질문:.

이 JSR-335를 하지 않기로 입니까?synchronized터페페 츠요시

수 있지만,synchronized디폴트 메서드의 수식어는 위험하다는 것이 판명되어 금지되었습니다.

는 몸 가 마치 입니다.synchronized잠금 객체가 리시버인 블록.이 시멘틱스를 디폴트 방식으로도 확장하는 것이 현명하다고 생각될 수 있습니다.주의주세요.synchronized꼭 한 것은 하는 구문적 보다 더 합니다.필요하지는 않습니다.대응하는 방법보다 더 콤팩트할 뿐입니다.synchronized더 많은 그 block. 이것은 애초에 통사적 최적화가 시기상조였고 동기화된 방법들이 해결보다 더 많은 문제를 일으킨다는 합리적인 주장이 있지만, 그 배는 오래 전에 출항했다.)

그럼, 왜 위험한 걸까요?동기화는 잠금이 중요합니다.잠금이란 공유 액세스를 가변 상태로 조정하는 것입니다.각 오브젝트에는 어떤 가드를 잠그는지 결정하는 동기화 정책이 있어야 합니다.(Java Concurrency in Practice 섹션 2.4 참조).

많은 객체는 Java Monitor Pattern(JCiP 4.1)을 동기화 정책으로 사용합니다.Java Monitor Pattern(JCiP 4.1)에서는 객체의 상태가 고유한 잠금으로 보호됩니다.이 패턴에는 마법이나 특별한 것은 없지만 편리하고, 이 패턴의 사용은synchronized이 패턴을 암묵적으로 상정하고 있습니다.

이 클래스는 해당 개체의 동기화 정책을 결정하는 상태를 소유하는 클래스입니다.단, 인터페이스는 혼재된 오브젝트 상태를 소유하지 않습니다.따라서 인터페이스에서 동기화된 방식을 사용하는 것은 특정 동기화 정책을 전제로 하지만 그 정책을 가정할 합리적인 근거가 없기 때문에 동기화를 사용해도 스레드의 안전성이 전혀 향상되지 않을 수 있습니다(잘못된 잠금으로 동기화할 수 있습니다).이로 인해 스레드 안전에 대해 뭔가 조치를 취했다는 잘못된 확신이 생기고 잘못된 동기화 정책을 가정하고 있다는 오류 메시지가 표시되지 않습니다.

단일 소스 파일의 동기화 정책을 일관되게 유지하는 것은 이미 충분히 어렵습니다.서브클래스가 슈퍼클래스에 의해 정의된 동기화 정책을 올바르게 준수하도록 하는 것은 더욱 어렵습니다.이와 같이 느슨하게 결합된 클래스(인터페이스와 그것을 실장하는 다수의 클래스) 간에 이를 실행하려고 하는 것은 거의 불가능하고 오류가 발생하기 쉽습니다.

반대되는 모든 주장들을 고려할 때, 무엇을 위한 주장일까요?대부분의 경우 인터페이스가 특성처럼 동작하도록 하기 위한 것 같습니다.이것은 이해할 수 있는 요구이지만, 디폴트 메서드의 설계 중심은 "트레이츠"가 아니라 인터페이스 진화입니다.양자가 일관되게 달성될 수 있는 곳에서는 그렇게 하기 위해 노력했지만, 한쪽이 다른 쪽과 충돌하는 경우에는 주요 설계 목표를 선택해야 했습니다.

public class ParentSync {

public synchronized void parentStart() {
    System.out.println("I am " + this.getClass() + " . parentStarting. now:" + nowStr());
    try {
        Thread.sleep(30000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("I am " + this.getClass() + " . parentFinished. now" + nowStr());
}

private String nowStr() {
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}
}


public class SonSync1 extends ParentSync {
public void sonStart() {
    System.out.println("I am " + this.getClass() + ". sonStarting,calling parent now ... ");
    super.parentStart();
    System.out.println("I am " + this.getClass() + ". sonFinished");
}
}



public class SonSync2 extends ParentSync {

public void sonStart() {
    System.out.println("I am " + this.getClass() + ". sonStarting,calling parent now ... ");
    super.parentStart();
    System.out.println("I am " + this.getClass() + ". sonFinished");
}
}



public class SyncTest {
public static void main(String[] args) throws Exception {

    new Thread(() -> {
        new SonSync1().sonStart();
    }).start();

    new Thread(() -> {
        new SonSync2().sonStart();
    }).start();

    System.in.read();
}
}

결과:

I am class com.common.interface18_design.whynotsync_onmethod.SonSync1. sonStarting,calling parent now ... 
I am class com.common.interface18_design.whynotsync_onmethod.SonSync2. sonStarting,calling parent now ... 
I am class com.common.interface18_design.whynotsync_onmethod.SonSync2 . parentStarting. now:2019-04-18 09:50:08
I am class com.common.interface18_design.whynotsync_onmethod.SonSync1 . parentStarting. now:2019-04-18 09:50:08
I am class com.common.interface18_design.whynotsync_onmethod.SonSync1 . parentFinished. now2019-04-18 09:50:38
I am class com.common.interface18_design.whynotsync_onmethod.SonSync1. sonFinished
I am class com.common.interface18_design.whynotsync_onmethod.SonSync2 . parentFinished. now2019-04-18 09:50:38
I am class com.common.interface18_design.whynotsync_onmethod.SonSync2. sonFinished

(부모 클래스를 예로 사용한 점 죄송합니다)

결과로부터, 우리는 부모 클래스 잠금이 모든 서브 클래스에 의해 소유된다는 것을 알 수 있었습니다. SonSync1과 SonSync2 오브젝트는 다른 오브젝트 잠금이 있습니다.모든 잠금은 독립적입니다.그래서 이 경우 부모 클래스 또는 공통 인터페이스에 동기화된 것을 사용하는 것은 위험하지 않다고 생각합니다.

언급URL : https://stackoverflow.com/questions/23453568/what-is-the-reason-why-synchronized-is-not-allowed-in-java-8-interface-methods

반응형