프로그래밍언어/JAVA

<JAVA>멀티스래드 프로그래밍-3

컴퓨터과학 2020. 12. 13. 17:55

2020/12/13 - [JAVA] - 멀티 스레드 프로그래밍 -2

이전글:

 

멀티 스레드 프로그래밍 -2

이전글: 2020/12/13 - [JAVA] - 멀티스래드 프로그래밍-1 임계 영역 두개 이상의 스레드가 동시에 접근하게 되는 리소스 임계영역에 동시에 스레드가 접근하게 되면 실행 결과를 보장할수 없음 스레드

kwaksh2319.tistory.com

DeadLock:

2020/10/21 - [컴퓨터과학/운영체제] - <운영체제17> 교착 상태

 

<운영체제17> 교착 상태

정의: 상호베제에 의해 나타나는 문제점으로, 둘 이상의 프로세스들이 자원을 점유한 상태에서 서로 다른 프로세스 점유하고 있는 자원을 요구하며 무한정 기다리는 현상 필요충분조건: 상호베

kwaksh2319.tistory.com

wait()/notify():

wait():

리소스가 더이상 유효하지 않는 경우 리소스가 사용가능할떄 까지 위해서 스레드를 non-runnable상태로 전환

wait상태가 된 스레드은 notify()가 호출될때까지 대기 

notify():

wait하고 있는 스레드중 한 스레드를 runnable 한 상태로 꺠움 

notifyAll():

wait하고 있는 모든 스레드가 runnable 한 상태가 되도록함

notify()보다 notifyAll()을 사용하기를 권장함

특정 스레드가 통지를 받도록 제어 할수 없으므로 모두 깨운후에 스케쥴러에 cpu를 점유하는것이 좀더 공평하다고함 

 

그렇다면 코드로 확인해보겠습니다.

 

먼저 학생은 6명 책은 3권이라는 도서관이라는 가정하겠습니다.

6명의 학생이 3권의 책을 동시 빌리려고하는데 선착순이어서 먼저 온 학생 한테 빌려주고 책이 없는경우 wait()를 시키고 책이 반납하면 notifyAll을 시킵니다.

package Test01;

import java.io.IOException;
import java.util.ArrayList;

class LibraryTest{
	
	public ArrayList<String> books=new ArrayList<String>();
	public LibraryTest(){
		books.add("드래곤라자");
		books.add("해리포터");
		books.add("반지의제왕");
	
	}
	public synchronized String lendBook() throws InterruptedException {
		Thread t=Thread.currentThread();
		while(books.size()==0) {
			System.out.println(t.getName()+"waiting start");
			wait();
			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");
	}
	
}

class Student extends Thread{
	public void run() {
		
		try {
			String title=Main.library.lendBook();
			if(title ==null) return ;
			sleep(5000);
			Main.library.returnBook(title);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}


public class Main {

	public static LibraryTest library=new LibraryTest();
	public static void main(String [] args) throws InterruptedException {
		Student st1=new Student();
		Student st2=new Student();
		Student st3=new Student();
		Student st4=new Student();
		Student st5=new Student();
		Student st6=new Student();
		
		st1.start();
		st2.start();
		st3.start();
		st4.start();
		st5.start();
		st6.start();
	
		//st8.start();
	}
	
	
}

위의 코드를 한번 쪼개서 간단하게 확인해보겠습니다.

 

도서관 클래스:

책은 리스트로 드래곤라자, 해리포터, 반지의 재왕 각 세권의 책이 존재합니다.

 lendBook()은 책을 빌려주는 메서드이며 

returnBook(String title)은 책을 반환하는 메서드 입니다. 

여기서 books.size()==0이면 wait()를 불러서 잠시 스레드를 대기 상태로 만듭니다. 

그리고 returnBook가 불릴때마다 notifyAll()을 불러서 대기상태를 전부 꺠웁니다.

그렇다면 여기서 책이 1권만 반납하면 나머지 2사람은 책이 없는 상태인데 이때 

다시 while(books.size()==0)을 통해서 책이 0권이지를 계속해서 체크해줍니다.

 

class LibraryTest{
	
	public ArrayList<String> books=new ArrayList<String>();
	public LibraryTest(){
		books.add("드래곤라자");
		books.add("해리포터");
		books.add("반지의제왕");
	
	}
	public synchronized String lendBook() throws InterruptedException {
		Thread t=Thread.currentThread();
		while(books.size()==0) {
			System.out.println(t.getName()+"waiting start");
			wait();
			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");
	}
	
}

학생 클래스:

학생 클래스는 책을 빌리고 5초 이후에 반납하도록 합니다. 

class Student extends Thread{
	public void run() {
		
		try {
			String title=Main.library.lendBook();
			if(title ==null) return ;
			sleep(5000);
			Main.library.returnBook(title);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

메인 클래스:

public class Main {

	public static LibraryTest library=new LibraryTest();
	public static void main(String [] args) throws InterruptedException {
		Student st1=new Student();
		Student st2=new Student();
		Student st3=new Student();
		Student st4=new Student();
		Student st5=new Student();
		Student st6=new Student();
		
		st1.start();
		st2.start();
		st3.start();
		st4.start();
		st5.start();
		st6.start();
	
		//st8.start();
	}
	
	
}

그렇다면 한번 결과를 확인해보겠습니다. 

결과: