자바 동기화 잠금 및 -synchronized 잠금

A, 동기화 키워드

1 동기화 프로필

각 객체가 로크로서 사용될 수있는 자바 : 동기화 기준은 동기화를 달성한다. 잠금이 스레드가 동기화 코드에 액세스하려고 할 때 해제해야하는 경우, 먼저 객체 잠금 장치, 종료를 얻거나 예외를 throw해야합니다.

: 폼의 블록 동기화 하고 동기화하기위한 방법 .


2 동기화 사용 시나리오

  • 동기화 방법

public synchronized void method1(){}复制代码

개체가 잠겨 인스턴스를 동기화하는 방법에서 개체의 인스턴스가 다른 스레드에서 스레드는 잠금을 얻을 호출 할 때, 나머지는 차단됩니다. 이 클래스에 다른 스레드하지만 만약 의 다른 인스턴스 객체가 수행하는 이 동기화 방법을 서로 다른 잠금을 사용하기 때문에, 당신은 차단되지 않습니다.


  • 동기화 코드 블록

synchronized(this)( //ToDo}
或
synchronized(普通变量){    }复制代码

같게


  • 정적 동기식 방법

public synchronized static void method3(){}复制代码

다른 스레드가 클래스 호출 할 때이 클래스는, 잠겨 정적 동기화 방법 만이있을 때 잠금을 얻기위한 하나 개의 스레드를 , 나머지 스레드가 차단됩니다 .


  • 정적 코드 블록

synchronized(Test.class){ //ToDo}
或
synchronized(静态变量){ //ToDo}复制代码

같게


3 동기화 잠금 에스컬레이션

로우에서 하이로 잠금 상태 수준의 네 가지 종류가 있습니다이 있습니다 : 잠금 장치가없는 상태 , 바이어스 잠금 상태 , 경량 잠금헤비급 잠금

잠금 업그레이드 할 수 있지만 다운 그레이드 할 수 없습니다, 바이어스 잠금 수단은 바이어스는 경량 잠금 장치를 잠금으로 다운 그레이드 할 수 없습니다 업그레이드 할 수 있습니다.

  • 바이어스 잠금

큰 경우에만 편향된 잠금 도입 비용 절감을 허용하기 위해 동일한 스레드, 스레드에 의해 여러 번 경쟁하지만, 항상하지 아니 멀티 스레드 잠금이 없습니다.

액세스 및 동기화 코드를 하나 개의 스레드가 로크를 획득 할 때, 로크는 스레드가 종료 후 헤드 바이어스 잠금 저장된 스레드 ID의 스택 프레임에서 오브젝트를 기록 할 동기 로크 재진입 잠금이 작동하고 CAS 필요가 없다 잠금을 해제, 단순히 마크 말씀의 머리가 실행 바이어스 잠금의 현재의 thread에 저장된 객체 여부를 테스트 할 수 있습니다.

바이어스 잠금 효과는 다음과 같습니다 경쟁의 다른 스레드가 없을 때,있다 바이어스는 현재 스레드, 현재의 thread가 실행되었을 수 있습니다.


  • 경량 잠금 (스핀 잠금)

경량 잠금에서 업그레이드에 의해 바이어스 잠금.

스레드의 경우 바이어스 로크 조작은 동기 블록을 입력 로크가 경량 바이어스 잠금으로 업그레이드 될 때, 두번째 쓰레드 로크 경합에 첨가 될 때.

  • 헤비급 잠금

경량 잠금 장치의 확장 후, 잠금 헤비급으로 업그레이드됩니다.

헤비급 모니터 잠금 달성 및 달성 모니터링 및 운영 체제에 의존 MutexLock (뮤텍스) 할 때 (헤비 로크 인 동기) 또한 헤비급 잠금 뮤텍스 알려진 내부 로크 대상에 의존한다.


바이어스 잠금

장점 : 추가 잠금없고 잠금 해제 소비

단점 : 경쟁 스레드가, 추가적인 잠금 해지 소비를 가져올 것이다

장면 : 장면에 하나의 스레드 동기화 블록 액세스

경량 잠금

장점 : 스레드가 경쟁을 차단 프로그램의 응답 속도를 개선하지 않습니다.

단점 : CPU를 해제하지 않습니다 때 스핀 스레드

장면 : 응답 시간을 추구는, 동기 블록은 매우 빠르게 수행.

헤비급 잠금

장점 : 경쟁이 CPU를 자유롭게, 스핀 스레드를 사용하지 않습니다

단점 : 스레드가 차단되고, 응답 시간이 느립니다.

장면 : 특정 동기 블록 긴 실행 속도의 추구.


두 잠금 인터페이스

1, 잠금 인터페이스

잠금, 잠금 객체. 잠금 전에 인터페이스는 잠금 기능을 달성하기 위해 동기화 된 키워드 자바 프로그램에 의해 나타납니다. 그리고 새로운 계약 및 Java SE5.0 후 잠금 인터페이스에 잠금 기능을 달성했다.

이 키워드 유사한 동기화 기능을 동기화하지만, 두 개의 보완 텍스트 사이의 차이로 얻을 및 잠금을 해제 보여줄 필요가 제공합니다.


메인 인터페이스 방법을 잠금 :

  • 무효 잠금 ()

상기 방법을 수행 할 때, 로크가 유휴 상태에있을 때, 현재의 스레드가 로크를 획득한다. 잠금 다른 thread에 의해 보유 된 경우 반대로, 현재의 thread가 잠금이 금지되어 취득.


  • 부울의 tryLock ()

잠금을 사용할 수있는 경우, 잠금을 얻을, 즉시, 그렇지 않은 경우는 false, true를 돌려줍니다.

차이의 tryLock () 및 잠금 ()이다 :

설정된 tryLock ()는 그냥 잠금을 얻기 위해 시도하는 경우 잠금 장치를 사용할 수없는 , 현재의 thread가 비활성화 발생하지 않습니다 , 현재의 thread가 아래 코드를 실행하고 있습니다.

잠금 () 경우, 잠금을 받아보실 수 있습니다 잠금을 사용할 수없는 그것, 대기 잠금을 얻을 수없는 때까지, 현재의 thread가 자신의 아래로 계속되지 않습니다.


  • 보이드 해제 ()

상기 방법을 수행 할 때, 현재의 스레드가 로크은 어떤 스레드가 로크를 보유하지 않는 경우,이 방법의 실행은 예기치 않은 방식으로 발생할 수 있고, 상기 홀더에 의해 해제 될 수 있고, 잠금을 해제 보유하고있다.


  • 조건 newCondition ()

조건 개체, 알림 구성 요소를 얻기 위해 기다리고. 조립 및 현재 잠금 바인딩, 잠금을 획득하는 유일한 현재의 thread가, 호출 후, 현재의 스레드가 잠금을 해제, 구성 요소 () 메소드를 기다리고 호출합니다.


2, ReentrantLock와 사용

동기화 잠금을 해제하기 위해 동기화 잠금을 얻기 위해, 단지 전화를 보여주고, 사용이 매우 간단 ReentrantLock와.

ReentrantLock lock = new ReentrantLock(); //参数默认false,不公平锁
.....................

try {
    lock.lock(); //如果被其它资源锁定,会在此等待锁释放,达到暂停的效果
    //操作
}catch(Exception e){
   //异常处理
} finally {
    lock.unlock();  //释放锁
}复制代码

높은 동시 성능의 조건에서 사용 ReentrantLock와 잠금, 동기화 된 키워드보다 훨씬 높은 수준이다.

그리고 reentratnlock 공정과 불공정 로크 큐 내부적 로크를 유지하기 위해 관리를 기반으로 이중 연결리스트 , 테이블 값은 노드 각각이 현재 쓰레드 로크를 요청하는 노드이다.


3,하는 ReadWriteLock 인터페이스

다음과 같이 주요 인터페이스를하는 ReadWriteLock :

public interface ReadWriteLock {
    /**
     * Returns the lock used for reading.
     *
     * @return the lock used for reading
     */
    Lock readLock();

    /**
     * Returns the lock used for writing.
     *
     * @return the lock used for writing
     */
    Lock writeLock();
}复制代码

하는 ReadWriteLock 잠금 집합을 관리하고, 읽기 전용 잠금 쓰기 잠금입니다.

자바 동시성 라이브러리 ReentrantReadWriteLock 인터페이스를 구현하는 ReadWriteLock의 재진입 기능을 추가했다.


잠금 읽기 에서 같은 시간에 여러 개의 스레드를 접근하지만, 쓰기 과정은 모든 액세스 할 리더 스레드기타 쓰기 프로세스가 되어 차단을 .

잠금 유지 보수 쓰기 잠금의 쌍, 읽기 잠금 및 쓰기 잠금 스루, 읽기 - 쓰기 잠금 분리 단독 잠금이 크게 개선 된 것으로 일반적인 동시성과 비교를.


몇 가지 기능은 잠금 읽기 - 쓰기 ReentrantReadWriteLock :

  • 선택적 공정
  • 요각
  • 잠금 다운 그레이드


(로부터 프로그램 읽기 - 쓰기 잠금 예를 들면 blog.csdn.net/canot/artic…인터넷 : ) :

public class Cache{
  static Map<String,Object> map = new HashMap<String,Object>();
  static ReentrantReadWriteLock  rwl = new ReentrantReadWriteLock();
  static Lock rLock = rwl.readLock();
  static Lock wLock = rwl.writeLock();

  //获取一个key对应的value
  public static final Object get(String key){
     r.lock();
     try{
         return map.get(key);
     }finally{
         r.unlock();
     }
  }

  //设置key对应的value并返回旧的value
  public static fianl Object put(String key,Object value){
     w.lock();
     try{
        return map.put(key,value);
     }final{
        w.unlock();
     }
  }

  //清空缓存
  public static fianl void clear(){
     w.lock();
     try{
        map.clear();
     } finally{
        w.unlock();
     }
  }
}复制代码


  • - 읽기, 쓰기 잠금 잠금 다운 그레이드

잠금 다운 그레이드 다운 그레이드 읽기 잠금 될 수있는 쓰기 잠금을 의미한다. 현재 스레드가 쓰기 잠금을 보유하는 경우 프로세스는 다음 읽기 잠금 잠금 강등을 호출 할 수 없습니다 얻기 위해 다시 놓습니다. 잠금 다운 그레이드는 쓰기 잠금 재 획득을 잡고시 잠금 해제라는 읽기 잠금 전에 잠금 릴리스 이후에 쓰기의 과정에 들어가, 잠금을 읽을 수 있다는 것을 의미한다.

(으로부터 파생 된 blog.csdn.net/qq_38737992…프로그램 : )

public void work() {
        reentrantReadWriteLock.readLock().lock();
 
        if (!update) {
            reentrantReadWriteLock.readLock().unlock();
 
            // 锁降级开始
            reentrantReadWriteLock.writeLock().lock();
            try {
                if (!update) {
                    // 准备数据
                    ++index;
                    try {
                        TimeUnit.MILLISECONDS.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    update = true;
                }
                reentrantReadWriteLock.readLock().lock();
            } finally {
                reentrantReadWriteLock.writeLock().unlock();
                // 锁降级结束,降级为读锁
            }
        }
        try {
            // 使用数据
            for (int i=0; i<5; i++) {
                try {
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":" + index);
            }
        } finally {
            reentrantReadWriteLock.readLock().unlock();
        }
    }
复制代码


세, 동기화 및 잠금 차이

1, 동기화 및 잠금 차이

인터페이스 잠금이 동기화 키워드

동기화 된 상태는 잠금이 잠금을 획득할지 여부를 결정할 수있는 잠금을 획득 할 수 있는지 여부를 판별 할 수 없습니다

잠금 해제 자동 동기 (자동 잠금을 해제 할 스레드를 실행 한 후, 동기 코드, 록 해제 예외는 스레드 B를 실행하는 동안 발생)

수동으로 잠금을 해제 마지막으로 잠금 (잠금 해제 () 메소드는 잠금을 해제), 또는 가능성이 스레드 교착 상태가 발생할하기 위해 필요.

차단 된 스레드 1, 스레드 2 영원히 기다릴 경우 두 키워드 실 1 실 2, 1 현재 스레드가 잠금을 획득하는 경우, 실이 대기를 동기화.

잠금 잠금 반드시, 더 이상 기다릴 당신이 끝날 때, 스레드가 기다리고있다하지 않을 수 있습니다 잠금을 시도하는 경우보다 적은받지 않습니다.


잠금 동기화 재진입을, 불공정 중단 될 수 없습니다 .

잠금 잠금 재진입, 인터럽트를 공정하게

잠금 에 대한 잠금 동기 코드 동기화를 많이 , 동기화 에 대한 잠금 코드가 동기화 문제의 소량


비 재진입 잠금 : 스핀 잠금, (,) (의 notifyAll 통지) (대기)

재귀 적으로 호출 할 수 없습니다 비 재진입 잠금, 재귀 호출의 교착 상태가 계속된다


2 ReentrantLock와 동기화 된 차분

ReentrantLock와는 다중 열 잠금뿐만 아니라, 시간 잠금 중단 기다리고 기다리고 투표, 같은 동기 동시성 및 메모리 의미를 가지고

동기화 잠금을 사용, A는 해제하지 않습니다, B 영원히 기다릴 것

ReentrantLock와 잠금 장치를 사용하여, A는 해제하지 않습니다, B는 약간의 시간 인터럽트 대기 시간을 기다린 다른 일을 할 것입니다.


동기화 에서 JVM 수준 에서 구현 동기화 잠금을 모니터링 할 수 있습니다뿐만 아니라, 코드가 실행될 때 예외가, JVM은 방출 모니터링 도구를 잠금의 숫자를 통해 올 것이다. 그러나 잠금하지

자원 경쟁이 매우 치열한 상황이 아니다에서는 동기화 성능이 ReentrantLock와 잠금보다 더 몇 번하고, 경쟁 상황, 동기화 가을의 성능, 정상적인 성능 ReentrantLock와을 유지하기 위해.


  • 성능 분석

동기화 됩니다 반복적으로 잠금을 얻기 위해 회전 이 과정에서 대기, 중단되지 않습니다 스레드 때문에 중단 오버 헤드 절감 및 웨이크 업 컨텍스트 스위칭,

그리고 ReentrantLock와는 , 회전,하지만 직접 끊지

스레드가이 경우에 비해 너무, 심지어 스핀없이 바이어스 잠금을 중지하기 때문에 그들이 스핀 잠금, 잠금 및 경량 잠금 바이어스 이유가 있기 때문에 동기화 동시 스레드의 소량의 경우, 기다리지 않는다 효율적인 reenttrantlock.


기본적으로 불공정 잠금을 동기화, 기본이 아닌 공정한 잠금을 ReentrantLock와.


  • 여러 조건을 바인딩

ReentrantLock와의 객체는 동시에 여러 상태의 객체를 바인딩 할 수 있습니다,

동기화에서, 객체의 잠금 wait()notify()또는 notifyAll()방법이 숨겨진 상태로 구현 될 수있다.

당신은 협회와 하나 이상의 시간을 추가 할 경우, 동기화 된은 별도의 잠금 장치를 추가했고, ReentrantLock와 너무에만 여러 호출해야 할 필요가 없습니다 new Condition()할 수있는 방법은.


추천

출처juejin.im/post/5db943fd51882564635002c2