WAIT 및 BLOCKED 스레드 상태의 차이점


101

스레드 상태 WAIT와 스레드 상태 BLOCKED의 차이점은 무엇입니까?

Thread.State 문서 :

차단됨
모니터 잠금을 기다리면서 차단 된 스레드가이 상태에 있습니다.

Waiting
다른 스레드가 특정 작업을 수행 할 때까지 무기한 대기중인 스레드가이 상태입니다.

나에게 차이점을 설명하지 않습니다.


이 스레드 stackoverflow.com/questions/2534147/java-thread-wait-blocked 에서 답변을 확인하십시오. 또한이 링크는 추가 설명을 제공 할 수 있습니다. geekexplains.blogspot.cz/2008/07/…
Abdul

@Abdul geekexplains 링크에 따르면 스레드가 Object.wait ()를 호출하여 차단 된 상태로 들어갈 수 있다고합니다.
개 이상

oracle docs docs.oracle.com/javase/6/docs/api/java/lang/… 에 따르면 : 스레드가 다음 메소드 중 하나를 호출하여 대기 상태에 있습니다. 시간 제한없이 Object.wait, Thread.join 없음 시간 제한, LockSupport.park와
압둘

기록을 위해 @Flavio의 답변이 Ankit보다 약간 낫다고 생각합니다.
회색

답변:


80

스레드는 wait()Object를 호출하면 대기 상태가됩니다 . 이를 대기 상태 라고 합니다. 스레드가 대기 상태에 도달하면 다른 스레드가 호출 될 때까지 notify()또는 notifyAll()객체 에서 기다려야 합니다.

이 스레드가 알림을 받으면 실행할 수 없습니다. 다른 스레드도 알림을 notifyAll()받거나 (사용 ) 첫 번째 스레드가 작업을 완료하지 않았기 때문에 기회가있을 때까지 여전히 차단 될 수 있습니다. 이를 차단 상태 라고 합니다. Blocked 상태는 스레드가 객체에 대한 잠금을 획득하려고 시도하고 다른 스레드가 이미 잠금을 보유하고있을 때마다 발생합니다.

다른 스레드가 떠나고이 스레드 기회가되면 JVM 스레딩 메커니즘을 기반으로 작업을 선택하고 실행 상태로 이동 한 후 Runnable 상태로 이동합니다.


2
스레드가 두 상태에 도달하는 순서를 설명했기 때문에 훨씬 더 잘 설명했습니다. 두 상태를 각각 분리하여 설명하는 것보다 더 명확합니다 ( "More Than Five"의 답변
Kumar Manish

7
웹 클레임에서 발견 된 대부분의 상태 다이어그램이 왜 (모두?) 궁금한 모든 사람들에게 notify () / notifyAll () 결과가 BLOCKED 대신 RUNNABLE이됩니다. stackoverflow.com/questions/28378592/…
Niklas Peter

스레드가 하나 뿐이고 밀리 단위로 일정 시간 동안 기다렸다 고 가정합니다. 이제 스레드가 대기 상태에서 직접 실행 가능 상태로 이동할 수 있습니까? 단 하나의 스레드이기 때문에 다른 스레드가 여기서 잠금을 취하지 않기 때문에?
Kanagavelu Sugumar

시간이 경과하면 실행 가능한 상태로 돌아가는 wait (time) 메서드가 있습니다. 그러나 시간을 지정하지 않으면 다른 스레드가 알리거나 스레드가 중단 될 때까지 대기합니다.
Ankit Bansal

2
귀하의 대답은 좋지만 잠금을 얻으려고 할 때마다 Blocked 상태로 들어갈 수 있다는 것을 설명하지 않습니다. 신호 / 알림과 관련이 없습니다.
회색

90

차이점은 비교적 간단합니다.

에서 BLOCKED상태, 스레드가 입력하는 것입니다 synchronized블록을하지만, 현재 내에서 실행중인 다른 스레드가 synchronized같은 객체에 블록. 첫 번째 스레드는 두 번째 스레드가 블록을 종료 할 때까지 기다려야합니다.

에서 WAITING 상태, 스레드는 다른 스레드로부터 신호를 기다리고있다. 이것은 호출하여 일반적으로 발생 Object.wait(), 또는 Thread.join(). 그러면 스레드는 다른 스레드가를 호출 Object.notify()하거나 죽을 때까지이 상태를 유지 합니다.


2
스레드 자체 만 대기 상태로 만들 수 있다고 말하는 것이 맞습니까? Thread-B가 Thread-A를 WAIT 상태로 만들 수 있습니까?
개 이상

1
Object.wait()직접 사용 하는 경우는 거의 없지만 WAITING두 스레드가 조정해야 할 때마다 잠금, 차단 대기열 등과 같은보다 높은 수준의 동시성 구조를 사용 하는 상태가됩니다.
Flavio

1
개인적인 경험으로 볼 때 IO를 기다리는 스레드 (예 : 소켓에서 읽기)는 RUNNING상태입니다.
Flavio

4
Java8 문서 Thread.State는 "... 이러한 상태는 운영 체제 스레드 상태를 반영하지 않는 가상 머신 상태입니다."라고 말합니다. 즉, JVM은 Java 코드를 실행하는 스레드, 시스템 호출이 반환되기를 기다리는 스레드 또는 타임 슬라이스를 기다리는 스레드 간의 차이에 대해 신경 쓰지 않습니다. 그것들은 모두 RUNNABLEJVM에 관한 것입니다.
솔로몬은 천천히

3
스레드가 WAITING상태 에서 이동할 BLOCKED때 대기중인 객체와 관련된 잠금을 획득 할 수있을 때까지 먼저 상태로 이동해야한다는 점을 추가하는 것이 좋습니다 .
그레이

22

차단 상태와 대기 상태의 중요한 차이점은 스케줄러에 미치는 영향입니다. 차단 된 상태의 스레드가 잠금을 위해 경쟁하고 있습니다. 해당 스레드는 여전히 스케줄러가 서비스해야하는 것으로 간주되어 실행중인 스레드를 제공 할 시간에 대한 스케줄러의 결정에 고려 될 수 있습니다 (스레드가 잠금을 차단할 기회를 줄 수 있음).

스레드가 대기 상태에 있으면 시스템에 가해지는 스트레스가 최소화되고 스케줄러는 이에 대해 걱정할 필요가 없습니다. 알림을받을 때까지 휴면 상태가됩니다. OS 스레드를 점유하고 있다는 사실을 제외하고는 완전히 작동하지 않습니다.

이것이 notifyAll을 사용하는 것이 이상적이지 않은 이유입니다. 이전에는 시스템에 부하를주지 않고 휴면 상태였던 스레드가 깨어나고 대부분의 스레드가 잠금을 획득하고 상태를 찾을 때까지 차단됩니다. 기다리는 것은 사실이 아니므로 다시 기다리십시오. 진행할 가능성이있는 스레드에만 알리는 것이 좋습니다.

(내재 잠금 대신 ReentrantLock을 사용하면 하나의 잠금에 대해 여러 조건을 가질 수 있으므로 알림 스레드가 특정 조건에서 대기중인 스레드인지 확인하여 스레드가 알림을받는 경우 분실 알림 버그를 방지 할 수 있습니다. 행동 할 수없는 것.)


모니터 객체에서 notify ()를 호출하는 것이 다른 스레드의 책임이기 때문입니까?
berimbolo

@berimbolo : 당신이 요구하는지 이해하지 않는다
나단 휴즈

대기중인 스레드가 스케줄러가 걱정할 필요가없는 이유에 관한 것입니다. 다른 스레드가 대기중인 경우 알림을 호출 할 책임이 있기 때문인지 궁금했습니다.
berimbolo

@berimbolo : 대기중인 스레드는 결국 알림에 의해 깨어납니다. 스케줄러는 알림을받을 대기 스레드를 결정합니다.
Nathan Hughes

카운트 무엇인가, 당신은 스핀 잠금, 차단 한 복용량을 의미하지 말 것은 스핀 잠금입니다
프랭크 장

16

스레드 덤프 해석을위한 단순화 된 관점 :

  • 잠깐만 -일을 기다리고있어서 지금은 게으른 상태입니다.
  • 차단됨 -작업을 완료하려고 바쁘지만 다른 스레드가 방해가되어 지금은 유휴 상태입니다.
  • RUNNABLE ... (Native Method) -JVM에 관한 한 일부 네이티브 코드 (아직 완료되지 않은)를 실행하도록 요청했습니다. RUNNABLE이며 추가 정보를 제공 할 수 없습니다. 일반적인 예는 실제로 트래픽이 도착하기를 기다리는 C로 코딩 된 네이티브 소켓 리스너 메서드이므로 지금은 유휴 상태입니다. 이 상황에서 이것은 우리가 실제로 RUNNING (CPU 소모 없음)이 아니기 때문에 특별한 종류의 WAIT로 볼 수 있지만이를 보려면 Java 스레드 덤프가 아닌 OS 스레드 덤프를 사용해야합니다.

1
나는 당신의 설명을 좋아합니다. 즉 :) 제가 분석 스레드에서 일을하려고하고있어 지금 덤프 정확히
스리 Sarnobat

@MuhammadGelbana 네, 맞아요, 댓글을 삭제했습니다.
Eric Wang

1
당신 RUNNABLE은 옳지 않습니다. Java 실행 큐에 있지만 실행 중이 아니거나 Java 코드를 실행 중일 수 있습니다. 고국을 부를 필요는 없습니다.
회색

1

차단됨-스레드가 스레드 수명주기의 실행 가능한 상태에 있으며 개체 잠금을 얻으려고합니다. Wait- 스레드가 스레드 수명주기의 대기 상태에 있으며 알림 신호가 스레드의 실행 가능 상태가되기를 기다리고 있습니다.


-1

이 예를 참조하십시오.

스레드 상태의 데모.

/*NEW- thread object created, but not started.
RUNNABLE- thread is executing.
BLOCKED- waiting for monitor after calling wait() method.
WAITING- when wait() if called & waiting for notify() to be called.
  Also when join() is called.
TIMED_WAITING- when below methods are called:
 Thread.sleep
 Object.wait with timeout
 Thread.join with timeout
TERMINATED- thread returned from run() method.*/
public class ThreadBlockingState{

public static void main(String[] args) throws InterruptedException {
    Object obj= new Object();
    Object obj2 = new Object();
    Thread3 t3 = new Thread3(obj,obj2);
    Thread.sleep(1000);
    System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+
            ",when Wait() is called & waiting for notify() to be called.");
    Thread4 t4 = new Thread4(obj,obj2);
    Thread.sleep(3000);
    System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+",After calling Wait() & waiting for monitor of obj2.");
    System.out.println("nm:"+t4.getName()+",state:"+t4.getState().toString()+",when sleep() is called.");
}

}
class Thread3 extends Thread{
Object obj,obj2;
int cnt;
Thread3(Object obj,Object obj2){
    this.obj = obj;
    this.obj2 = obj2;
    this.start();
}

@Override
public void run() {
    super.run();
    synchronized (obj) {
        try {
            System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before Wait().");
            obj.wait();             
            System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After Wait().");
            synchronized (obj2) {
                cnt++;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}
class Thread4 extends Thread{
Object obj,obj2;
Thread4(Object obj,Object obj2){
    this.obj = obj;
    this.obj2 = obj2;
    this.start();
}

@Override
public void run() {
    super.run();
    synchronized (obj) {
        System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before notify().");
        obj.notify();
        System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After notify().");
    }
    synchronized (obj2) {
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}

코드 주셔서 감사합니다.하지만 텍스트 답변을 받고 작은 코드 블록 을 보여 주셨으면합니다 .
회색
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.