오답노트
[Java] Multi Thread Synchronization 본문
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 |