JDK 소스 코드 분석 슈 자바 스레드

스레드 관련 개념

스레드는 프로세스의 부 프로세스의 실제 동작에 포함되는 시스템 자원 할당의 최소 단위이다. JVM은 각 스레드는 낮은 우선 순위의 스레드 실행을 통해 높은 우선 순위 스레드의 우선 순위가 우선 순위를 가지고, 애플리케이션을 동시에 실행하는 복수의 스레드를 실행할 수있게

자바에서 쓰레드는 두 가지 범주로 나눌 수 있습니다 User Thread(用户线程),Daemon Thread(守护线程)

JVM의이 주요 기능, 주요 기능은 사용자 스레드가,이 글의 새로운 스레드가 기본 사용자 스레드 있다는 것이다 스레드를 호출 시작할 때, 그러나에 의해 (참) Thread.setDaemon이 데몬 스레드를 설정할 수 있습니다 (에있을 스레드. 시작 () 호출 전에). JVM 유모 데몬 스레드는 모든 비 데몬 스레드 가장 일반적인 애플리케이션 데몬 스레드 GC (가비지 수집)에 있다는

만큼 JVM의 현재 인스턴스가 JVM의 마지막 스레드의 끝, JVM 스레드의 보호자가 함께 끝으로 때 아닌 스레드 데몬, 사용자의 모든 작업에서 데몬 스레드를 생존 어떤로 끝나지 않는


스레드 생성 모드

스레드를 생성하는 방법에는 두 가지가 있습니다 继承 Thread 类,实现 Runnable 接口

Thread 클래스 자체가 생성 된 Runnable 인터페이스를 구현하여 수행됩니다. 스레드가 생성 될 때 스레드의 이름을 지정할 수, 이름이 반복 될 수있다. 스레드가 생성 될 때 이름을 지정하지 않으면, 스위치는 새 이름을 생성합니다

상속 Thread 클래스가 생성되고 시작됩니다 :

     class PrimeThread extends Thread {
         long minPrime;
         PrimeThread(long minPrime) {
             this.minPrime = minPrime;
         }

         public void run() {
             // compute primes larger than minPrime
         }
     }
复制代码
     PrimeThread p = new PrimeThread(143);
     p.start();
复制代码

실행 가능한 인터페이스를 생성하고 시작을 구현하는 :

     class PrimeRun implements Runnable {
         long minPrime;
         PrimeRun(long minPrime) {
             this.minPrime = minPrime;
         }

         public void run() {
             // compute primes larger than minPrime
         }
     }
复制代码
     PrimeRun p = new PrimeRun(143);
     new Thread(p).start();
复制代码

스레드 상태 변경

스레드의 국가가 할 수 Thread소스 카테고리에서 찾을 수, 총 NEW여섯 : RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED,,

    public enum State {

        NEW, // 尚未启动状态

        RUNNABLE, // 可运行状态,但它可能还在等待处理器资源分配

        BLOCKED, // 阻塞状态

        WAITING, // 等待状态,等待另一个线程执行完毕

        TIMED_WAITING, // 定时等待状态

        TERMINATED; // 终止状态,线程已执行完毕
    }

复制代码


주요 방법의 Thread 클래스 소스

Thread.start는 () : 스레드를 시작합니다

당신이) (시작를 호출 할 때, 첫 번째, 즉이 스레드를 시작하는 처음 여부를 확인합니다 threadStatus == 0경우, threadStatus != 0허용되지 않는 현재 반복 시작에 대한 설명이 스레드는 예외 오류 상태가 발생합니다IllegalThreadStateException

확인 후, 기 스레드 것 현재 스레드는 오브젝트의 인스턴스를 추가함으로써 group, 기본 방식을 통과 한 후에 start0()스레드 동작의 실행을 개시한다. 완료 시작한 후 threadStartFailed()제거 내를, 자원의 석방을 수행 하였다

    public synchronized void start() {

        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                ···
            }
        }
    }

    private native void start0();
复制代码

Thread.stop를 () : 강제 정지 스레드 실행

이 방법은 동일한 결과, 처리는 완전히 다르다 완료 오히려 정상적인 종료 작업을 통해 대신하여 전원을 차단 것처럼, 예상치 못한 결과를 야기 할 수 있으며, 안전하지

통화는 stop()발생합니다 ThreadDeath예외에게이 시간이 run방법을 통해 수행, 스레드가 중단 것, 그리고이 예외가 발생하는 스레드의 끝

모든 잠금이 유지 대해 호 Thread.stop를가 (후) 스레드 결과 경우 서브 스레드에 의해 보유 된 모든 로크 일반 코드 블록 로크의 해제 후에는, 데이터의 일관성을 보호하기위한 것이다 (통제) 갑자기 릴리스, 다음이 손상 이러한 데이터의 사용에 보호 된 데이터의 불일치, 다른 스레드 렌더링 할 수 있습니다, 그것은 매우 이상한 응용 프로그램 오류가 발생할 수 있습니다

    @Deprecated
    public final void stop() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            checkAccess();
            if (this != Thread.currentThread()) {
                security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
            }
        }

        if (threadStatus != 0) {
            resume(); // Wake up thread if it was suspended; no-op otherwise
        }

        stop0(new ThreadDeath());
    }

    @Deprecated
    public final synchronized void stop(Throwable obj) {
        throw new UnsupportedOperationException();
    }
复制代码

Thread.run () : 스레드 블록을 실행하는 실제 코드

당신이 스레드를 시작하려는 경우, 그 주, 직접 통화 run()방식이 유효하지, 어떤 실제적인 결과를 생성하지 않습니다

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
复制代码

Thread.interrupt는 () : 합리적인를 달성하기 위해 인터럽트 상태를 수정하고 안전가 현재의 thread에 인터럽트

stop()이 방법은 또한 스레드를 중단 할 수 있지만, 즉시 종료하고, 알 수없는 문제로 이어질 것입니다, 그래서이 있었다 interrupt()데이터 보안을 보장하고, 스레드를 종료 조건을 달성 할 수있는 방법,

스레드가 중단 실현하기 위해 interrupt()충족해야 isInterrupted()하거나 interrupted(),이 두 방법은 인터럽트 플래그가 취득 할 수 있습니다 함께 사용 true, 우리는 적절한 치료를 얻은 후에 할 수 있습니다. 전화는 isInterrupted()인터럽트 상태를 반환하지만, 상태를 복원하지 않는 interrupted()인터럽트 상태를 반환하고 인터럽트 상태를 삭제에 사용 된 비즈니스의 실제 필요에 따라

    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }
复制代码
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }
复制代码
    public boolean isInterrupted() {
        return isInterrupted(false);
    }
复制代码

Thread.yield () : 다른 스레드가 CPU를 실행할 수 있도록, 현재의 thread의 실행을 중지 (하지만 무시 될 수 있습니다)

당신이 원하는 경우에 실제로, yield()그 역할을, 우리는 스레드가 일치 할 필요 优先级사용, 정확한 운영 절차는 CPU의 임기를 넣어, 어떤 경우 현재 우선 순위 스레드가 같은 상태로 실행할 수 있습니다와 같은 존재 여부를 감지하는 것입니다 이 스레드가 원래 스레드를 계속 실행하거나. 그래서 수율 () 메소드는 동일한 우선 순위의 다른 스레드를 실행할 수있는 기회를 제공하는 "양보"라고합니다.

    public static native void yield();
复制代码

또한 Thread.wait () / 또한 Thread.wait (롱) : 그들은 다시 깨어 또는 N 밀리 초 타이머를 기다릴 때까지 스레드는 실행 상태에서 철수 한 후, 공유 자원의 잠금을 해제하려면이 메서드를 호출하고 대기 큐에 진입 공지없이 시간 제한을 반환하는 경우

wait()그것은에 속하는 Object객체입니다. 제 잠금 동기 부호 또는 블록 (에 동기화하는 일반적인 방법 획득시 synchronized)에 의해 notify()또는 notifyAll()웨이크 업

    public final void wait() throws InterruptedException {
        wait(0);
    }

    public final native void wait(long timeout) throws InterruptedException;
复制代码

를 Thread.join () /를 Thread.join (롱) : 다음 나사 끝을 기다리고, 그리고 후 계속

그 역할은 주로 스레드 사이의 상호 작용에 대해, 스레드 우선 순위 스레드 실행은 완료되거나 중단 스레드 가입 호출 될 때까지 블록을 실행 가입을 호출하는 것

    public final void join() throws InterruptedException {
        join(0);
    }

    public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
复制代码

Thread.sleep를 (롱) : 지정된 시간 내에 중단, 현재의 thread

이 스레드 객체의 일시 중지를 호출하면 interrupt()스레드를 깨우고 던질 것이다 InterruptedException, 다음 진행

    public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }
复制代码

Thread.notify () / Thread.notifyAll () : 일어나 스레드 상태를 기다리고있다

일반적인 사용 시나리오는 스레드 A의 통화 대기 상태로 전환 할 수있는 대기 () 메소드의 B 객체이며, 다른 스레드 호출 큐 입력 대기중인 스레드에서 탈퇴 통지를받은 후 C 객체 B () /가는 notifyAll () 메소드를 통지 실행 가능한 상태로, 또한 후속 작업. 두 스레드 C와 B에 의해 대화 형 객체를 완료하고, 객체 대기 (의 관계) 및 통지 () /의 notifyAll () 메소드는 파티와 통지 자 사이의 상호 작용의 종료를 기다리고, 상기 스위칭 신호의 경우와 동일 일.

notify() 같은 공유 자원 스레드에 대한 임의 대기열 웨이크,이 스레드가 대기열에 다시 종료, 실행 가능한

notifyAll() 모든 스레드가 모든 대기열에 같은 공유 리소스를 기다리고 일어나 대기중인 모든 출구 큐, 실행 가능한이 가장 높은 우선 순위가 시작됩니다

   public final native void notify();

   public final native void notifyAll();
复制代码

Thread 클래스의 소스 코드를 다른 방법

currentThread는 ()는 : 현재 실행중인 스레드 객체 참조를 돌려줍니다

    /**
     * Returns a reference to the currently executing thread object.
     *
     * @return  the currently executing thread.
     */
    public static native Thread currentThread();
复制代码

이것은, 자바는 DLL의 기능을 달성하기 위해 전화를 기본 기능, C / C ++ 언어를 사용하여 구현하는이 방법의 아웃 기본 방법이며, DLL로 컴파일되면, JDK의 소스 코드가 포함되어 있지 않습니다 그래서 우리는 볼 수 없습니다. 이것은 자바가 실제로 운영 시스템에 대한 액세스를 달성하기 위해 서로 다른 플랫폼에 다른 네이티브 메소드를 호출, 자바의 기본 메커니즘이다.

    System.out.println("对象信息:" + Thread.currentThread());

    //// 输出结果
    对象信息:Thread[main,5,main]
复制代码

getID () 현재의 소재지 : 스레드의 ID를 반환

    /**
     * Returns the identifier of this Thread.  The thread ID is a positive
     * <tt>long</tt> number generated when this thread was created.
     * The thread ID is unique and remains unchanged during its lifetime.
     * When a thread is terminated, this thread ID may be reused.
     *
     * @return this thread's ID.
     * @since 1.5
     */
    public long getId() {
        return tid;
    }
    
    // tid 在 Thread 的 init 中赋值
    ···
    tid = nextThreadID();
    ···

    // tid 等于 threadSeqNumber,而 threadSeqNumber 专门被用来生成线程的 ID
    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }
复制代码

ID는 nextThreadID 방법은 스레드 안전 (동기 수정) 때마다 당신 ++ 새로운 스레드 ID의 TID를 생성하고 할당 nextThreadID 방법에 의해 생성 된 긴 나사의 종류,이다

    System.out.println("线程  ID:" + Thread.currentThread().getId());

    //// 输出结果(main方法中调用)
    线程  ID:1
复制代码

** getName은 () : ** 스레드의 이름을 가져옵니다

    /**
     * Returns this thread's name.
     *
     * @return  this thread's name.
     * @see     #setName(String)
     */
    public final String getName() {
        return name;
    }
复制代码

(0에서 시작하여 생성 된 스레드의 순서, N) String 형의 스레드 이름, 기본값은 스레드 N이다. 새로운 Thread ( "이름") 또는 Thread.setName ( "이름") : 물론, 스레드 클래스는, 즉 이름을 수정하는 두 가지 방법을 제공합니다

	Thread threadTest01 = new Thread();
	System.out.println("线程名称:" + threadTest01.getName());
	
	Thread threadTest02 = new Thread();
	System.out.println("线程名称:" + threadTest02.getName());
	
	Thread threadTest03 = new Thread("我有名字,我叫 T03");
	System.out.println("线程名称:" + threadTest03.getName());
	
	Thread threadTest04 = new Thread();
	threadTest04.setName("我有名字:我叫 T04");
	System.out.println("线程名称:" + threadTest04.getName());

    //// 输出结果
    线程名称:Thread-0
    线程名称:Thread-1
    线程名称:我有名字,我叫 T03
    线程名称:我有名字:我叫 T04

复制代码

getPriority는 () : 스레드 우선 순위를 가져옵니다

    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

    // 线程优先级在初始化(init)时设置,默认是等同于父线程优先级
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        ...
        Thread parent = currentThread();
        ···
        this.priority = parent.getPriority();
        ···
    }

    /**
     * Returns this thread's priority.
     *
     * @return  this thread's priority.
     * @see     #setPriority
     */
    public final int getPriority() {
        return priority;
    }
复制代码

부모 스레드 우선 순위의 기본 스레드 우선 순위 : this.priority = parent.getPriority();. 실행 순서를 우선 순위 스레드는 스레드이지만 높은 CPU 리소스를보다 우선권을 획득하는 확률을 결정할 수 없다

디폴트는 10 5 - 스레드의 우선 setPriority를 ​​(INT의 newPriority)는, (1)의 범위 파라미터를 제공 할

    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }
复制代码

그렇지 않으면 일이 일어날 최대 우선 순위보다 클 수 없습니다 스레드의 우선 순위를 설정할 때 즉, 참고 throw new IllegalArgumentException();그렇지 않으면 스레드 그룹의 우선 순위 재설정됩니다, 그것은 가장 높은 우선 순위의 스레드 그룹보다 클 수 없습니다 newPriority = g.getMaxPriority();다음과 같이 :

public static void main(String[] args) {
	
	ThreadMethods main = new ThreadMethods();
	Thread t01 = main.new MyThread01();
	Thread t02 = main.new MyThread02();
	
	t01.setPriority(Thread.MAX_PRIORITY);
	t02.setPriority(Thread.MIN_PRIORITY);
	
	t02.start();
	t01.start();
}

/**
 * @des 测试线程 01
 * */
class MyThread01 extends Thread{
	public void run() {
		super.run();
		
		for(int i = 0 ; i < 10 ; i++ ){
			System.out.println("MyThread01:" + i);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
} 

/**
 * @des 测试线程 02
 * */
class MyThread02 extends Thread{
	public void run() {
		super.run();
		
		for(int i = 0 ; i < 10 ; i++ ){
			System.out.println("MyThread02:" + i);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
} 

//// 输出结果
MyThread01:0
MyThread02:0
MyThread02:1
MyThread01:1
MyThread02:2
MyThread01:2
MyThread02:3
MyThread01:3
MyThread01:4
MyThread02:4
MyThread01:5
MyThread02:5
MyThread01:6
MyThread02:6
MyThread01:7
MyThread02:7
MyThread01:8
MyThread02:8
MyThread01:9
MyThread02:9
复制代码

일반적인 문제 스레드

이유는 교착 상태 및 방지하고 해결하는 방법

여러 개의 동시 스레드의 경우 교착 상태에 대한 이유는 차단하거나 스레드가 무한 차단되기 때문에 그들 모두는 출시 될 자원을 기다리고 있습니다,이 스레드 및 기타 자원의 나머지 부분은 해제 할 수 없습니다, 그래서 프로그램이 없습니다 두 사람이 키를 가지고 있지만 키를 넘겨 서로를 기다리고 있습니다 여는 데 필요한 두 개의 키와 함께로드 귀중한 보물 상자를, 그러나 그렇지 않은 : 다음 생생한 밤나무의 경우 정상 작동 (계속 자신의 키를 넘겨은) 된 교착 상태를 가지고

왜 교착?

교착 상태가 한 조건 중 하나라도 충족되지 않는 교착 상태가 발생하지 않습니다, 다음과 같은 네 가지 조건을 충족해야합니다

  • 상호 배타적 인 조건 : 자원은 다음 요청 프로세스는 기다릴 수 자원 요청을 공유하는 다른 프로세스가있을 경우이 번에 하나의 과정입니다 시간 이내에, 즉, 배타적 제어에 할당 된 자원의 요구 사항을 스레드 ...
  • 아니 박탈 : 완료를 사용하지 않을 전에 프로세스에서 얻은 자원을 다른 프로세스가 강제로 그에만 해제 자체 스레드의 자원 (활성 해제)에 의해 얻어진다, 박탈 할 수 없습니다.
  • 요청 및 보관 조건 : 스레드는 이미 하나 개 이상의 자원을 보유하고 있지만, 새로운 자원 요청을 제안, 리소스가 다른 스레드에 의해 점령되었다,이 시간을 요청하는 스레드가 차단되어 있지만, 사용할 수있는 자원은 보류 상태를 유지하도록 할 수 있습니다.
  • 루프 조건을 기다린다 : 대기 루프 체인 스레드 리소스 체인을 요청하는 동안 각 스레드는 다음 스레드에 의해 수득 된 리소스 체인이 존재한다.

교착 상태 조건이 요약되어 있습니다 :

  1. 적어도 하나 개의 자원을 공유 할 수 없습니다
  2. 적어도 하나의 작업은 자원을 보유하고 다른 다른 작업에 의해 보유 자원의 취득을 대기한다
  3. 자원 작업을 선점 할 수 없습니다
  4. 주기가 기다려야합니다

어떻게 방지하고 교착 상태를 해결하기 위해?

1, 중첩 잠금을 방지하기 위해이 교착 상태의 가장 흔한 원인이며, 이미 자원이있는 경우, 다른 자원 잠금 피해주십시오. 하나의 오브젝트 만 잠금 경우는 교착 상태 회피 중첩 루프의 상부 부분의 코드는 다음과 같은 변형이 거의 불가능 교착 상황이다 :

public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " acquiring lock on " + obj1);
        synchronized (obj1) {
            System.out.println(name + " acquired lock on " + obj1);
            work();
        }
        System.out.println(name + " released lock on " + obj1);
        System.out.println(name + " acquiring lock on " + obj2);
        synchronized (obj2) {
            System.out.println(name + " acquired lock on " + obj2);
            work();
        }
        System.out.println(name + " released lock on " + obj2);

        System.out.println(name + " finished execution.");
    }
复制代码

2, 잠금의 일부가 그러한 위의 프로그램에서 필요에 리소스를 잠글 관리 필요가, 우리가 완전한 객체 자원을 고정,하지만 우리는 단 하나 개의 필드를 필요로하는 경우, 우리는 단지 특정 분야를 고정해야하며, 하지 완전한 객체

3 스레드를 사용하여 두 개의 스레드가 서로 교착 상태가 발생합니다, 우리는이 문제를 방지 할 수있는 최대 대기 시간을 설정할 수 있습니다 무한정 대기에 가입하면 무기한 대기 방지 할 수 있습니다.

종류 및 잠금 차에서 JAVA

코드를 실행하는 동안, 필요한 데이터의 일부는 최종 결과의 정확성의 배타적 제어를하는 장치는 데이터가 외부의 실행 중에 잠겨 수정되지 않도록 할 필요가 있는지 확인하기 위해이 메커니즘은 잠금 메커니즘은

다음 한편, 로크, 디자인, 상이한 상태의 특성에 따라, 및 엄격히 분류 될 수있다 :

공정 / 불공정 잠금 잠금

공정 잠금, 잠금이 불공정하지 완전히 무작위 순서 인 우선 순위 역전 굶주림 쇼를 일으킬 수 있습니다 위해 여러 스레드가 잠금을 얻기 위해 잠금을 적용하는 것을 의미한다

비 잠금 공정 동기화 ReentrantLock와 공정 불공정 잠금 래치의 생성자에 의해 결정될 수 있고, 잠금 모드가 아닌 공정은

비 팔 잠금 장치의 처리량 성능은 공정 이상을 잠 그려면

재진입 잠금

또한 재귀 잠금라고도 같은 스레드의 시간을 의미가있어서의 외층의 잠금을 획득하고, 상기 방법은 자동적으로 내측 잠금 얻을

동기화 및 ReentranLock 재진입 잠금이며, 교착 상태가 어느 정도 방지 할 수 있습니다

독점 잠금 / 공유 잠금

배타적 로크 로크 만 군에 의해 유지 될 수 있다는 것을 의미 공유 로크는 로크가 더 홀더로 생각 될 수 있다는 것을 의미

동기화 및 ReentranLock은 배타적 잠금입니다. 하는 ReadWriteLock 잠금은 배타적 잠금입니다 쓰기, 잠금은 공유 잠금입니다 읽어 보시기 바랍니다. ReentrantLock와 독점 잠금 및 공유 잠금은 AQS에 의해 달성된다

뮤텍스 / 읽기 - 쓰기 잠금

= 뮤텍스는 독점, 공유 잠금 = 쓰기 잠금 장치를 잠급니다. 뮤텍스 에센스 ReentrantLock와, 읽기 - 쓰기 잠금 에센스하는 ReadWriteLock

낙관적 / 비관적 잠금 잠금

그들은 특정 잠금 분류에 속하지만, 동시에 동기화의 각도에 보이지 않는

동시성에 대한 낙관적 잠금은 동시성 잠금 낙관적 인 생각, 업데이트하려고 끊임없이 다시 사용할 때 동일한 데이터가 모든 권리를 잠겨 있지, 수정하는 업데이트 데이터를 일어나지 않을 생각

동시 작동을 위해, 비관적 잠금이 통합 된 데이터의 형태를 취할 잠금 때문에 비관적 잠금이 해제 운영 문제가있을 것입니다 생각하기 때문에 비관적 잠금의 생각은 동시 작업의 동일한 데이터 수정을 위해 일한다

비관적 잠금 조작은, 많은 시나리오, 읽기 및 쓰기 장면의 많은에 대한 낙관적 잠금에 매우 적합한 성능을 크게 향상시킬 수 있습니다 잠금 해제

세그먼트 잠금

사실, 전략의 잠금이 아닌 특정 잠금. 동시 ConcurrentHashMap의 효율적인 구현 형태 로크 세그먼트의 동시 작동에 의해 달성된다

당신이 요소가 잠겨 있지 않은 전체 해시 맵을 넣고 싶지만 때 먼저 어떻게해야 넣어 멀티 스레드 요소의 다른 세그먼트에 배치 때와 같이 너무 오래, 다음 세그먼트가 잠겨있는 세그먼트 알고 해시 코드에 의해 배치 할 수있다 모든 통계 크기 세그먼트 잠금을 얻을 필요가있을 때 진정한 병렬 삽입, 그러나 계산하기

잠금 부분은 잠금 단위를 수정하도록 설계

바이어스 잠금 / 잠금 경량 / 헤비급 잠금

이 상태를 요약하는 로크에 따라, 그리고 동기화 대. 잠금을 획득 줄이기 위해 자바 1.6이 국가의 도입으로 인한 잠금 성능 문제를 해제, 그것은 점점 더 커지고있는 상황과 경쟁, 잠금 업그레이드 할 수 있지만 경량 되돌림으로 잠글 수있는 잠금 에스컬레이션을 바이어스 수단을 다운 그레이드 할 수 없습니다 이 다운 그레이드 할 업그레이드 전략의 목적은 라이브 락의 효율성을 개선하고 잠금을 해제하는 것입니다

스핀 락

사실, 뮤텍스의 개념에 대하여, 뮤텍스 스레드가 잠겨 컨텍스트 스핀 쓰레드 로크가있다 스위칭 CPU 선점 오버 헤드 RUNNABLE 상태를 포함하는 상태와 환상 RUNNABLE WAITING 상태 루프 검출 플래그 들어가 비트 메커니즘은 반복하지 않고, 뮤텍스 잠금 홀드 시간뿐만 로크 오버 헤드 초기 비용보다 작은 선형 증가가 있지만 스핀 잠금 전체 소비 CPU 잠글

인터럽트 잠금

중단되지 않습니다 동기화, 잠금 인터럽트이다

다음은 인터럽트 인터럽트를 기다리는 차단 작업이 중단되지 않고 내장


동기화 된 동기 잠금 원리

이 문서 거래 지속적으로 업데이트 스레드 관련 지식 격차의 즐거움을 해결하기 위해 함께 배울!

추천

출처juejin.im/post/5d4d41945188252d336992d4