Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Archives
Today
Total
관리 메뉴

Super Coding Addict

Ch15. 자바 Thread 프로그래밍 (5) - multi-thread 프로그래밍 본문

JAVA 문법

Ch15. 자바 Thread 프로그래밍 (5) - multi-thread 프로그래밍

밍응애 2021. 2. 15. 23:08

* deadlock

- 2개 이상의 Thread가 서로 기다림

 

* wait()와 notify() 메서드

- wait() : 리소스는 한정적이므로 리소스가 유효하지 않을 때 다시 available할 때까지 thread가 non-runnable상태로 전환되어 대기 --> notify()가 호출될 때까지 기다림

- notify() : wait()하고 있는 하나의 thread를 runnable하게 깨운다 (but the oldest가 아니라, 아무 thread나 깨움!)

-. notifyAll() : wait()하고 있는 모든 thread를 깨움

--> notifyAll()이 더 권장됨, 모든 thread를 다 깨워서 서로 CPU 점유 경쟁을 하게한 후, non-runnable한 thread는 다시 잠들게 된다

==> 특정 thread가 통지를 받도록 제어할 수 없어 모두 깨운 후 schedular가 CPU를 할당하는 것이 공평

 

- 예제

# 책대여반납

 

-- FastLibrary 클래스

class FastLibrary{
	
	public ArrayList<String> books = new ArrayList<String>();
	
	public FastLibrary() {	//생성자
		books.add("태백산맥 1");
		books.add("태백산맥 2");
		books.add("태백산맥 3"); //리소스 한정적!
	}
	
	public synchronized String lendBook() throws InterruptedException {
		Thread t = Thread.currentThread();
		
		while(books.size() == 0) {
			System.out.println(t.getName() + " waiting start");
			wait(); //currentThread를 기다리게함
			System.out.println(t.getName() + " waiting end");
		}
		
		String title = books.remove(0);
		System.out.println(t.getName() + ":" + title + " lend");
		return title;
	}
	
	public synchronized void returnBook(String title) {
		Thread t = Thread.currentThread();
		books.add(title);
		notifyAll();
		System.out.println(t.getName() + ":" + title + "return");
	}
}

 

-- Student 클래스

class Student extends Thread{
	
	public void run() {
		
		try {
			String title = LibraryMain.library.lendBook();
			if ( title == null) return; //책을 못빌리는 걸로 끝나게 됨
			sleep(5000);
			LibraryMain.library.returnBook(title);
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

 

-- LibraryMain 클래스

public class LibraryMain {
	
	public static FastLibrary library = new FastLibrary();

	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();
	}

}

 

--> 책은 3권이지만 학생은 6명이기에 리소스인 책이 한정되어 있다

--> 따라서 책 3권이 대여가 되면, 한 권이 반납될 때 비로소 다른 1명이 책을 대여할 수 있게 된다

--> books.size() == 0일 때가 바로 책 3권이 모두 대여가 되었을 때이고, 이 때 wait() 메서드 호출로 thread를 non-runnable 상태로 만든다

--> 이 때 non-runnable상태인 학생 thread은 1개 이상일 수 있다

--> 책 1권이 반납되면 notifyAll() 메서드를 호출해 non-runnable 상태에 있는 thread들을 모두 깨우고 깨어난 thread들 중 랜덤하게 책을 대여해가면 다시 books.size() == 0이 되어 나머지 thread들은 non-runnable한 상태로 다시 빠지게 된다 (while문으로 반복을 걸어놓았음)

 

 --> 결과를 살펴보면, 책 3권이 모두 대여가 되면 나머지 3명 학생들의 thread(3,4,5)는 wait()호출로 non-runnable한 상태에 빠지며, 태백산맥 1return과 동시에 notifyAll()로 thread(3,4,5)의 wait()가 끝이 났다가 태백산맥 1권이 다시 대여되어 대여할 책이 없게 되어 wait가 다시 시작되고 있음을 알 수 있다