컴퓨터공학 💻 도서관📚

Part2. 6-23 wait() / notify() 에서드를 활용한 동기화 프로그래밍 본문

✅🌲강의 복습 노트/패캠 JavaSpring 강의,코드 복습

Part2. 6-23 wait() / notify() 에서드를 활용한 동기화 프로그래밍

들판속초록풀 2025. 12. 25. 22:05
  • 리소스가 어떤 조건에서 더 이상 유효하지 않은 경우 리소스를 기다리기 위해 Thread 가 wait() 상태가 된다.
    wait() 상태가 된 Thread은 notify() 가 호출 될 때까지 기다린다.
  • 1. 유효한 자원이 생기면 notify()가 호출되고 wait() 하고 있는 Thread 중 무작위로 하나의 Thread를 재시작 하도록 한다.
  • 2. notifyAll()이 호출되는 경우 wait() 하고 있는 모든 Thread가 재시작 된다.  (리소스를 두고 Thread 끼리 경쟁)
    이 경우 유효한 리소스만큼의 Thread만이 수행될 수 있고 자원을 갖지 못한 Thread의 경우는 다시 wait() 상태로 만든다.
  • 자바에서는 notifyAll() 메서드의 사용을 권장한다.
    (모든 쓰레드를 깨워서 모든 쓰레드가 경쟁상태가 되는 게 훨씬 더 공평하다고 한다.)
  • 도서관에서 책을 빌리는 예제
    도서관에서 내가 원하는 책이 없는 경우,  이 책이 들어오면
    한 명한테만 책이 들어왔다는 알람을 주는 게 notify() 이고
    이 책을 기다린 모든 사람들한테 알람을 주는 게 notifyAll() 이다.

1. notify()를 사용하는 경우

class FastLibrary{
	
	public ArrayList<String> shelf = new ArrayList<String>();  // new ArrayList(); 로 쓰는 것도 가능, 즉 <String> 생략 가능
	
	public FastLibrary(){
		
		shelf.add("태백산맥 1");
		shelf.add("태백산맥 2");
		shelf.add("태백산맥 3");
	}
	
	public synchronized String lendBook() throws InterruptedException{  // 예외 throws : 여기서 예외처리 안 한다는 뜻
		
		Thread t = Thread.currentThread();
		
		if(shelf.size() == 0 ) {
			System.out.println(t.getName() + " waiting start");
			wait();                                        // wait() 는 Object 클래스의 메서드
			System.out.println(t.getName() + " waiting end");
		}
		String book = shelf.remove(0);
		System.out.println(t.getName() + ": " + book + " lend");
	
		return book;
	}
	
	public synchronized void returnBook(String book){
		Thread t = Thread.currentThread();
		
		shelf.add(book);
		notify();                     // 누구 한 명이 책을 반납하면 책 못 가진 쓰레드 다 깨움
		System.out.println(t.getName() + ": " + book + " return");
	}
	
}

class Student extends Thread{
	
	public void run(){          // 쓰레드가 start 하면 run 메서드 안에 있는 내용이 수행된다.

		try{
				
			
			String title = LibraryMain.library.lendBook();
			if( title == null ) return;
			sleep(5000);
			LibraryMain.library.returnBook(title);
			
		}catch (InterruptedException e) {
			System.out.println(e);
		}
	}
	
}

public class LibraryMain {        // public 클래스 LibraryMain

	public static FastLibrary library = new FastLibrary();   // static 참조변수 library
	public static void main(String[] args) {

		Student std1 = new Student();
		Student std2 = new Student();
		Student std3 = new Student();
		Student std4 = new Student();
		Student std5 = new Student();
		Student std6 = new Student();
		
		std1.start();
		std2.start();
		std3.start();
		std4.start();
		std5.start();
		std6.start();
	}

}

2. notifyAll()을 사용하는 경우

위에 있는 코드에서  lendBook()  /  returnBook() 메서드를 수정해야 한다.

 

다 깨웠는데  책을 못 빌리는 쓰레드가 생기면 다시 wait 를 하게 바꿔줘야 한다.

public synchronized String lendBook() throws InterruptedException{
		
		Thread t = Thread.currentThread();
		
		while( shelf.size() == 0 ){                   // while 로 바꿔줘야 한다.
			System.out.println(t.getName() + " waiting start");
			wait();
			System.out.println(t.getName() + " waiting end");
		}
		String book = shelf.remove(0);
		System.out.println(t.getName() + ": " + book + " lend");
		
		return book;
	}
}

public synchronized void returnBook(String book){

		Thread t = Thread.currentThread();
		
		shelf.add(book);
		notifyAll();                                      // notifyAll() 사용
		System.out.println(t.getName() + ": " + book + " return");
}

 

 

선생님의 마지막 조언
1. 한 책을 완독하려면 밥 먹듯이 하루에 몇 페이지씩 꾸준히 해야 한다.
2. 백문이 불여일타 :  영타에 빨라지고  코드가 손에 익숙해지면 코딩하는 게 굉장히 즐겁다.
     익숙해지면  잘하게 되고  잘하게 되면  좋아하게 된다.

Comments