오답노트

[Java] Multi Thread Synchronization 본문

Java

[Java] Multi Thread Synchronization

권멋져 2023. 7. 11. 14:42

Critical Section 과 Semaphore

Critical Section은 두 개 이상의 thread가 동시에 접근하는 경우 문제가 생길 수 있기 떄문에 동시에 접근할 수 없는 영역

Semapore는 특별한 형태의 시스템 객체이며 get/release 두 개의 기능이 있다.

한 순간 오직 하나의 thread만이 semaphore를 얻을 수 있고, 나머지 thread들은 대기(blocking) 상태가 된다.

Semaphore를 얻은 thread 만이 critical section에 들어갈 수 있다.

 

Synchronized

class Bank{
	private int money = 10000;
	
	public synchronized void saveMoney(int save) {
		int m = getMoney();
		
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		setMoney(m+save);
	}
	
	public  void minusMoney(int minus) {
		synchronized(this) {
			int m = getMoney();
			
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			setMoney(m-minus);
		}

	}
	
	public int getMoney() {
		return money;
	}

	public void setMoney(int money) {
		this.money = money;
	}
	
}

class Park extends Thread{
	public void run() {
		System.out.println("start save");
		SycnMain.bank.saveMoney(3000);
		System.out.println("save money : " + SycnMain.bank.getMoney());
	}
}

class ParkWife extends Thread{
	public void run() {
		System.out.println("start minus");
		SycnMain.bank.minusMoney(1000);
		System.out.println("minus money : " + SycnMain.bank.getMoney());
	}
}

public class SycnMain {
	public static Bank bank = new Bank();

	public static void main(String[] args) {
		
		ParkWife pw = new ParkWife();
		pw.start();

		try {
			Thread.sleep(200);
		} catch(InterruptedException e) {
			e.printStackTrace();
		}
		
		Park p = new Park();
		p.start();
		
	}

}

 

synchronized 는 메소드 방식과 블럭 방식이 존재한다. 좀 더 디테일한 동기화가 필요하다면 블럭 방식을 사용하도록 하자.

 

wait & notify

synchronized는 같은 자원에 두 개 이상의 쓰레드가 접근하여 발생하는 문제를 막아주었다.

wait & notify는 자원이 모자란 상황에서 쓰레드가 접근하려는 상황을 해결해준다.

 

책을 빌리려고 할 때, 책이 없다면 책을 빌리는 것을 포기하는 것이 아닌 반납될 때까지 기다려서 빌려야한다.

아래 코드는 위 상황을 코드로 구현한 것이다.

 

import java.util.ArrayList;

class FastLibrary{
	public ArrayList<String> shelf = new ArrayList<>();
	
	public FastLibrary() {
		shelf.add("book1");
		shelf.add("book2");

	}
	
	public synchronized String lendBook() throws InterruptedException {
		
		Thread t = Thread.currentThread();
		if(shelf.size() == 0) {
			System.out.println(t.getName() + " is waiting");
			wait();
			System.out.println(t.getName() + " is runnable");
		}
		if(shelf.size() != 0) {
			String book = shelf.remove(0);
			System.out.println(t.getName() + " : " + book + " lend");
			return book;
		}
		else return null;

	}
	
	public synchronized void returnBook(String book) {
		Thread t = Thread.currentThread();
		shelf.add(book);
		notifyAll();
		System.out.println(t.getName() + " : " + book + " return");
	}
}

class Student extends Thread{
	public Student(String name) {
		super(name);
	}
	public void run() {

		try {
			String title = LibararyMain.libray.lendBook();
			if(title == null) {
				System.out.println(getName() + " cant lend");
				return;
			}
			sleep(5000);
			LibararyMain.libray.returnBook(title);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

public class LibararyMain {
	public static FastLibrary libray = new FastLibrary();
	public static void main(String[] args) {
		Student std1 = new Student("std1");
		Student std2 = new Student("std2");
		Student std3 = new Student("std3");
		Student std4 = new Student("std4");
		Student std5 = new Student("std5");
		
		std1.start();
		std2.start();
		std3.start();
		std4.start();
		std5.start();
		
	}

}

'Java' 카테고리의 다른 글

[JSP] JSP 에서 한글 깨짐  (0) 2024.05.06
[Spring JPA] Spring Data JPA  (0) 2023.07.18
[Java] Thread  (0) 2023.07.11
[Java] 직렬화  (0) 2023.07.11
[Java] IOStream  (0) 2023.07.10