>  기사  >  Java  >  동기화와 잠금의 차이점은 무엇입니까?

동기화와 잠금의 차이점은 무엇입니까?

青灯夜游
青灯夜游원래의
2020-11-19 11:38:2968681검색

차이점: 1. Lock은 인터페이스이고, 동기화는 Java의 키워드입니다. 2. 동기화는 예외가 발생할 때 보유하고 있는 잠금을 자동으로 해제하므로 교착 상태가 발생하지 않습니다. 예외가 발생하면 동기화는 보유하고 있는 잠금을 적극적으로 해제하지 않으며 잠금을 수동으로 해제해야 하므로 교착 상태가 발생할 수 있습니다.

동기화와 잠금의 차이점은 무엇입니까?

분산 개발에서 잠금은 스레드를 제어하는 ​​중요한 방법입니다. Java는 또한 이러한 목적을 위해 동기화 및 잠금이라는 두 가지 잠금 메커니즘을 제공합니다.

0. 동기화된 구현 원칙

Java의 모든 객체는 동기화를 달성하기 위한 기본입니다.

  • 일반적인 동기화 방법, 잠금은 현재 인스턴스 객체입니다

  • 정적 동기화 방법, 잠금은 현재 클래스의 클래스 개체입니다.

  • 동기화 방법 블록, 잠금은 괄호 안의 개체입니다.
    스레드가 동기화된 코드 블록에 액세스할 때 먼저 잠금을 획득해야 합니다. 종료되거나 예외가 발생하면 잠금을 해제해야 합니다. 그러면 이 메커니즘을 어떻게 구현합니까? 먼저 간단한 코드를 살펴보겠습니다.

package cn.alibab.javap;public class SynchronizedTest {

    public synchronized void test1(){

    }    public void test2(){        synchronized (this){

        }
    }
}

javap 도구(javap은 Java 컴파일 후 클래스 파일의 분해자임)를 사용하여 생성된 클래스 파일 정보를 보고 동기화

동기화와 잠금의 차이점은 무엇입니까?

동기화와 잠금의 차이점은 무엇입니까?
위에서 보면 동기화된 코드 블록은 monitorenter 및 monitorexit 명령어를 사용하여 구현되고 동기화된 메서드(JVM의 기본 구현을 살펴봐야 한다는 것은 여기서 명확하지 않습니다)는 다음에 의존한다는 것을 알 수 있습니다. 메소드 수정자에 대한 ACC_SYNCHRONIZED 구현.

동기화된 코드 블록: monitorenter 명령어는 컴파일 후 동기화된 코드 블록의 시작 부분에 삽입되고, monitorexit 명령어는 동기화된 코드 블록의 끝에 삽입됩니다. JVM은 각 monitorenter에 monitorexit가 있는지 확인해야 합니다. 그것에 해당합니다. 모든 개체에는 연결된 모니터가 있습니다. 모니터를 잡고 있으면 잠긴 상태가 됩니다. 스레드가 monitorenter 명령을 실행할 때 개체에 해당하는 모니터 소유권을 얻으려고 시도합니다. 즉, 개체의 잠금을 얻으려고 시도합니다. [동시 프로그래밍 기술에서 발췌]

동기화 방법 : 동기화된 메소드는 일반 메소드 호출로 변환되며,invokevirtual, areturn 명령어와 같은 반환 명령어는 동기화된 메소드를 구현하기 위한 VM 바이트코드 수준의 특별한 명령어가 없습니다. 대신 access_flags의 동기화된 플래그 위치입니다. 메소드의 필드는 클래스 파일의 메소드 테이블에서 1로 설정되어 메소드가 동기화된 메소드이고 JVM의 내부 객체 표현 Klass에서 메소드를 호출하는 객체 또는 메소드가 속한 클래스를 사용함을 나타냅니다. 잠금 객체. (출처: http://www.cnblogs.com/javaminer/p/3889023.html)

synchronized와 lock

동기화와 잠금의 차이점은 무엇입니까?
의 차이점은 다음과 같습니다.

  • 출처:
    lock 인터페이스이고 동기화는 Java의 키워드이며 동기화는 내장된 언어 구현입니다.

  • 예외가 발생할 때 잠금이 해제되는지 여부:
    동기화는 예외가 발생할 때 보유하고 있는 잠금을 자동으로 해제합니다. 교착 상태가 발생하지 않으며 잠금에서 예외가 발생하면 점유된 잠금이 적극적으로 해제되지 않습니다. 잠금을 해제하려면 수동으로 잠금을 해제해야 하며 이로 인해 교착 상태가 발생할 수 있습니다. (따라서 교착 상태 발생을 피하기 위해 최종적으로 try catch 및 write Unlock으로 동기화 코드 블록을 래핑하는 것이 가장 좋습니다.)

  • 인터럽트에 응답할지 여부
    잠금 대기 프로세스 중에 인터럽트를 사용하여 다음을 수행할 수 있습니다. 동기화되는 동안에만 대기를 중단합니다. 잠금이 해제될 때까지 기다릴 수 있지만 인터럽트에 응답할 수는 없습니다.

  • 잠금을 획득할지 여부를 알고 계십니까? 잠금은 trylock을 사용하여 잠금이 획득되었는지 알 수 있지만 동기화되었습니다.

  • Lock은 읽기 작업을 위한 다중 스레드의 효율성을 향상시킬 수 있습니다. (readwritelock을 통해 읽기와 쓰기 분리가 가능합니다)

  • 성능면에서 리소스 경쟁이 치열하지 않으면 둘의 성능은 거의 비슷하지만, 리소스 경쟁이 매우 치열한 경우(즉 즉, 동시에 경쟁하는 많은 수의 스레드가 있습니다.) 이때 Lock 성능은 동기화 성능보다 훨씬 좋습니다. 그러므로 사용시 상황에 맞게 선택해야 합니다.

  • synchronized는 Object 개체 자체의 wait, inform 및 informAll 예약 메커니즘을 사용하는 반면 Lock은 Condition을 사용하여 스레드 간 예약을 수행할 수 있습니다.

  • //Condition定义了等待/通知两种类型的方法
    Lock lock=new ReentrantLock();
    Condition condition=lock.newCondition();...condition.await();...condition.signal();
    condition.signalAll();

1 동기화와 잠금 간의 사용법 차이

synchronized. : in 동기화가 필요한 개체에 이 컨트롤을 추가합니다. 동기화는 메서드나 특정 코드 블록에 추가할 수 있습니다. 잠가야 하는 개체는 괄호 안에 표시됩니다.

lock: 일반적으로 ReentrantLock 클래스가 잠금으로 사용됩니다. 잠금 및 잠금 해제 위치는 lock() 및 Unlock()을 통해 표시되어야 합니다. 따라서 교착상태를 방지하기 위해 일반적으로 Unlock()을 finally 블록에 작성합니다.

2. 동기화와 잠금의 성능 차이

synchronized는 JVM 실행을 위해 호스팅되며,

잠금은 잠금을 제어하기 위해 Java로 작성된 코드입니다.

Java1.5에서 동기화는 성능이 비효율적입니다. 이는 작업 인터페이스를 호출해야 하는 무거운 작업이므로 잠금은 잠금 이외의 작업보다 시스템 시간을 더 많이 소비할 수 있습니다. 대조적으로, Java에서 제공하는 Lock 객체를 사용하면 성능이 더 높아집니다.

하지만 Java 1.6에서는 상황이 바뀌었습니다. 동기화는 의미론적으로 매우 명확하며 적응형 스핀, 잠금 제거, 잠금 조대화, 경량 잠금, 바이어스 잠금 등을 포함한 많은 최적화를 수행할 수 있습니다. 결과적으로 Java1.6의 동기화 성능은 Lock보다 나쁘지 않습니다. 관계자들은 또한 더 많은 동기화를 지원하며 향후 버전에서는 최적화할 여지가 있다고 밝혔습니다.

두 메커니즘의 구체적인 차이점은 다음과 같습니다.
synchronized는 원래 CPU 비관적 잠금 메커니즘을 사용했습니다. 즉, 스레드가 배타적 잠금을 얻습니다. 배타적 잠금은 다른 스레드가 스레드가 잠금을 해제할 때까지 대기하기 위해 차단에만 의존할 수 있음을 의미합니다. CPU 변환 스레드가 차단되면 스레드 컨텍스트 전환이 발생합니다. 잠금을 위해 경쟁하는 스레드가 많으면 CPU의 컨텍스트 전환이 자주 발생하여 효율성이 매우 낮습니다.

And Lock은 낙관적 잠금 방식을 사용합니다. 소위 낙관적 잠금은 충돌이 없다고 가정하고 매번 잠금을 수행하지 않고 작업을 완료하는 것입니다. 충돌로 인해 실패하면 성공할 때까지 재시도합니다. 낙관적 잠금으로 구현된 메커니즘은 CAS 작업 (비교 및 교환)입니다. ReentrantLock의 소스 코드를 더 자세히 연구하면 잠금을 얻는 가장 중요한 방법 중 하나가 CompareAndSetState라는 것을 알 수 있습니다. 이는 실제로 호출된 CPU가 제공하는 특수 명령입니다.

최신 CPU는 공유 데이터를 자동으로 업데이트하고 다른 스레드의 간섭을 감지할 수 있는 명령을 제공하며, CompareAndSet()은 잠금 대신 이를 사용합니다. 이 알고리즘을 비차단 알고리즘이라고 하며, 이는 한 스레드의 실패 또는 일시 중단이 다른 스레드의 실패 또는 일시 중단에 영향을 주어서는 안 된다는 것을 의미합니다.

3. 동기화 목적과 잠금 목적의 차이점

일반적인 상황에서는 동기화된 기본 요소와 ReentrantLock 사이에 차이가 없지만, 매우 복잡한 동기화 애플리케이션에서는 특히 다음 두 가지 요구 사항이 충족될 때 ReentrantLock 사용을 고려하세요.

1. 잠금 제어를 기다리는 동안 특정 스레드를 중단해야 합니다
2. 일부 대기 알림은 별도로 처리해야 합니다. ReentrantLock의 조건 애플리케이션은 알림을 보낼 스레드를 제어할 수 있습니다. 모든 들어오는 스레드는 줄을 서서 기다립니다

자세히 이야기해 보겠습니다...

먼저 첫 번째 경우에 대해 이야기해 보겠습니다. ReentrantLock에는 인터럽트 잠금을 무시하고 인터럽트 잠금에 응답하는 두 가지 잠금 메커니즘이 있습니다. 문제가 많습니다. 예를 들어 두 스레드 A와 B가 잠금을 위해 경쟁하는 경우 스레드 A는 잠금을 획득하고 스레드 B는 현재 처리할 작업이 너무 많아 스레드 B가 반환하지 못할 수 있습니다. 더 이상 기다리지 말고, 이 잠금 장치를 기다리는 것을 멈추고 다른 일로 전환하고 싶습니다. 이때

ReentrantLock은 중단 가능/중단 불가능이라는 2가지 메커니즘을 제공합니다. 먼저 스레드 B가 스스로 중단하지만(또는 다른 스레드가 이를 중단) ReentrantLock은 응답하지 않고 스레드 B를 계속 기다리게 합니다. 어떻게 중단할 수 있습니까? 귀를 기울이지 않았습니다(동기화 프리미티브의 경우).
두 번째, 스레드 B가 스스로 인터럽트하거나(또는 다른 스레드가 이를 인터럽트) ReentrantLock이 인터럽트를 처리하고 더 이상 잠금이 도착할 때까지 기다리지 않고 완전히 포기합니다.

더 많은 프로그래밍 관련 지식을 보려면

프로그래밍 비디오를 방문하세요! !

위 내용은 동기화와 잠금의 차이점은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.