[해 혹] 스 레 드 대기 와 방출 을 정확하게 이해 합 니 다 (wait / notify)

초보 자 에 게 아래 의 이 예 는 매우 흔히 볼 수 있 는 잘못 이다.
/**
 *    A:   50        ,   B  。
 */
class ThreadA extends Thread{
	 //          	
	Object oa=null;
	
       ThreadA(Object o){
		this.oa=o;
	}
	//  A    
	public void run(){
                //      ,          
		synchronized(oa){
			System.out.println("ThreadA is running......");
			for(int i=0;i<100;i++){
				System.out.println("   ThreadA value is "+i);
				if(i==50){
					try {
                                               //      
						Thread.currentThread().wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}//if(i==50)
			}//for(int i)
		}
	}
}
/**
 *    B:    A   ,        ,       A
 */
class ThreadB extends Thread{
	 //          	
	Object ob=null;
	
	ThreadB(Object o){
		this.ob=o;
	}
	//  B    
	public void run(){
		//      ,          
               synchronized(ob){
			System.out.println("ThreadB is running......");
			for(int i=0;i<50;i++){
				System.out.println("   ThreadB value is "+i);
			}
                      //       
			notify();
		}
	}
}
//  
public class ThreadTest {  
	 public static void main(String[] args){
		 Object lock=new Object(); //     
		 ThreadA threada=new ThreadA(lock);
		 ThreadB threadb=new ThreadB(lock);
		 threada.start(); //  A  
		 threadb.start(); //  B  
	 }
}  

     프로그램 은 매우 간단 하 다. 바로 라인 A, B 를 교체 해서 인쇄 하 는 것 이다.하지만 실행 할 때 두 가지 이상 을 던 집 니 다.
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread not owner
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException: current thread not owner
 
     문 제 는 ThreadA 의 Thread. current Thread (). wait () 입 니 다.ThreadB 의 notify ();올라가다
 
     초보 자 들 은 wait () 를 이해 할 때 현재 스 레 드 를 막 는 것 이 라 고 생각 하기 때문에 Thread. currentThread (). wairt ();보기에 매우 일리 가 있다.하지만 JDK 라 이브 러 리 에서 wait () 와 notify () 방법 은 Thread 류 가 아니 라 Object () 에 있 는 것 으로 밝 혀 졌 는 지 모르겠다.wait 방법의 JDK 문 서 를 자세히 살 펴 보 겠 습 니 다.
 
    public final void wait() throws InterruptedException
 
    다른 스 레 드 에서 이 대상 을 호출 하 는 notify() 방법 이나 notifyAll() 방법 전에 현재 스 레 드 가 기 다 립 니 다.이 방법 은 wait (0) 호출 만 수행 하 는 것 과 같다 는 얘 기다.
    현재 스 레 드 는 이 대상 모니터 를 가지 고 있어 야 합 니 다.이 스 레 드 는 이 모니터 의 소유권 을 발표 하고 다른 스 레 드 가 호출 notify 방법 이나 notifyAll 방법 으로 이 대상 의 모니터 에서 기다 리 는 스 레 드 가 깨 어 날 때 까지 기 다 립 니 다.그리고 이 스 레 드 는 모니터 에 대한 소유권 을 다시 얻 은 후에 야 계속 실 행 될 것 이다.  
    특정한 매개 변수의 버 전에 대해 중단 과 허위 각성 을 실현 하 는 것 이 가능 하 며 이 방법 은 항상 순환 에서 사용 해 야 합 니 다.
                                    synchronized (obj) {                                            while ()                                                  obj.wait();                                            // Perform action appropriate to condition                                      }
     이 방법 은 이 대상 모니터 의 소유자 스 레 드 로 만 호출 되 어야 합 니 다.
     던 지기: IllegalMonitorStateException - 현재 스 레 드 가 이 대상 모니터 의 소유자 가 아니라면.
               InterruptedException - 현재 스 레 드 가 알림 을 기다 리 기 전이 나 알림 을 기다 리 고 있 을 때 모든 스 레 드 가 현재 스 레 드 를 중단 합 니 다. 이 이상 을 던 졌 을 때 현재 스 레 드 의 중단 상태 가 삭 제 됩 니 다.
 
 
    JDK 문 서 를 보고 시작 한 프로그램 에서 Thread. current Thread (). wait (), oa. wait (), notify (), ob. notify () 로 바 꾸 면 문제 가 없 음 이 분명 합 니 다.
 
     즉, 동기 블록 obj 를 통 해 wait / notify 방법 을 호출 할 수 있 을 뿐, 당연한 스 레 드 를 통 해 이 두 가지 방법 을 호출 할 수 없습니다. 왜 그런 지 에 대해 서 는 한 가지 생각 이 있 습 니 다. 여러분 은 함께 토론 할 수 있 습 니 다.
 
      우선, 우 리 는 JVM 이 모든 대상 에 게 유일한 자 물 쇠 를 분배 할 것 이라는 것 을 알 고 있 습 니 다. 이 자 물 쇠 는 대상 에 있 습 니 다.
      그리고 Thread - 0 스 레 드 가 이 자 물 쇠 를 가 져 왔 을 때 대상 의 잠 금 에 현재 자신의 스 레 드 번 호 를 기록 하고 사용 중인 것 으로 설정 해 야 합 니 다. 그러면 Thread - 0 이 자 물 쇠 를 포기 해 야 할 때 잠 금 대상 은 Thread - 0 을 잠 금 대기 열 에 넣 습 니 다. 이 모든 것 은 Thread - 0 과 아무런 관계 가 없습니다. Thread - 0 대상 으로 바 꿀 수도 없습니다.어떤 방법 으로 다른 대상 의 자 물 쇠 를 바 꿔 라.
      따라서 공공 데이터 구역 대상 의 자 물 쇠 를 바 꾸 는 방법 은 공 데이터 구역 대상 본 성 을 통 해 호출 되 고 스 레 드 대상 과 관계 가 없다.
 
      사실 모든 동기 화 잠 금 lock 아래 에 준비 (Ready) 대기 열, 대기 (Waiting) 대기 열 등 몇 개의 스 레 드 대기 열 이 걸 려 있 습 니 다. 스 레 드 A 가 동기 화 잠 금 lock 을 얻 지 못 해 lock. Ready Queue (준비 대기 열) 에 들 어 갑 니 다. 동기 화 잠 금 이 점용 되 지 않 으 면 JVM 은 자동 으로 준 비 된 대기 열 에 있 는 스 레 드 를 실행 합 니 다. notify () 가 필요 하지 않 습 니 다.동작 합 니 다. 하지만 스 레 드 A 가 wait () 에 걸 리 면 lock. WaitingQuene (대기 열) 에 들 어 갑 니 다. 동시에 차지 하 는 동기 화 잠 금 도 포기 합 니 다. 이 때 동기 화 잠 금 이 대기 열 에 있 는 프로 세 스 (lock. notify () 를 깨 우지 않 으 면 이 프로 세 스 는 실행 할 기 회 를 얻 지 못 합 니 다.
 
      준비 대기 행렬 과 대기 행렬 이 크게 다르다 는 점 을 명심 하 세 요.
 
      object 의 wait, notify, notify All 에 대한 이 해 는 '자바 가상 컴퓨터 시스템 구조' 의 메모리 저장 소 내용 을 참조 하면 더욱 깊이 이해 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기