728x90
반응형
Thread Synchronization
두 개의 쓰레드가 동일한 객체에 접근을 하려고 할 때 공유 자원을 lock하여 다른 쓰레드가 접근하지 못하게 합니다. 그래서 두 개의 쓰레드가 공유자원에 동시에 접근하여 발생하는 문제를 없앨 수 있습니다.
Thread Synchronization Problem
package Java.thread.syncronizedEx;
import static java.lang.Thread.sleep;
class Bank{
private int money = 10_000;
public void saveMoney(int save){
int curMoney = getMoney();
try {
sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
setMoney(curMoney + save);
}
public void minusMoney(int minus){
int curMoney = getMoney();
try {
sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
setMoney(curMoney - minus);
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
class Save extends Thread{
public void run(){
System.out.println("start save");
SyncMain.myBank.saveMoney(3000);
System.out.println("saveMoney(3000): " + SyncMain.myBank.getMoney());
}
}
class Minus extends Thread{
public void run(){
System.out.println("start minus");
SyncMain.myBank.minusMoney(1000);
System.out.println("minusMoney(1000): " + SyncMain.myBank.getMoney());
}
}
public class SyncMain {
public static Bank myBank = new Bank();
public static void main(String[] args) throws InterruptedException {
Save save = new Save();
save.start();
sleep(200);
Minus minus = new Minus();
minus.start();
//결과
/**
* start save
* start minus
* minusMoney(1000): 9000
* saveMoney(3000): 13000
*/
}
}
문제
3000원을 저장하는 쓰레드는 작업이 3초가 걸리고 1000원을 사용하는 쓰레드는 0.2초가 걸립니다.
이 때 고유자원인 Bank에 두 쓰레드가 동시에 접근하기 때문에 결과 값이 원하는 값과 다르게 출력되었습니다.
이 문제를 해결하기 위해서는 3000원을 저장하는 쓰레드 작업과 1000원을 사용하는 쓰레드 작업이
동시에 실행되면 안됩니다. 즉 3000원을 저장하는 쓰레드 작업 수행 시 1000원을 사용하는 작업은 대기를 해야 합니다.
Bank는 공유자원이기 때문에 동기화를 해주어야합니다. 쓰레드가 사용중일 때는 lock을 걸고 사용이 끝난 후 lock을 풀어서
다른 쓰레드가 사용할 수 있도록 해야하는 것입니다.
Java Synchronized 메서드 구현
package Java.thread.syncronizedEx;
import static java.lang.Thread.sleep;
class Bank{
private int money = 10_000;
//실제 동작하는 메서드에 synchronized 키워드 추가
public synchronized void saveMoney(int save){
int curMoney = getMoney();
try {
sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
setMoney(curMoney + save);
}
//실제 동작하는 메서드에 synchronized 키워드 추가
public synchronized void minusMoney(int minus){
int curMoney = getMoney();
try {
sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
setMoney(curMoney - minus);
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
class Save extends Thread{
public void run(){
System.out.println("start save");
SyncMain.myBank.saveMoney(3000);
System.out.println("saveMoney(3000): " + SyncMain.myBank.getMoney());
}
}
class Minus extends Thread{
public void run(){
System.out.println("start minus");
SyncMain.myBank.minusMoney(1000);
System.out.println("minusMoney(1000): " + SyncMain.myBank.getMoney());
}
}
public class SyncMain {
public static Bank myBank = new Bank();
public static void main(String[] args) throws InterruptedException {
Save save = new Save();
save.start();
sleep(200);
Minus minus = new Minus();
minus.start();
//결과
/**
* start save
* start minus
* saveMoney(3000): 13000
* minusMoney(1000): 12000
*/
}
}
결론
Synchronized 키워드를 사용해서 멀티 쓰레드 동기화 작업을 해보았습니다.
728x90
반응형
'JAVA' 카테고리의 다른 글
[Java] Adapter Pattern (0) | 2022.07.31 |
---|---|
[Java] Thread Method : wait(), notify() (0) | 2022.07.31 |
[Java] Thread Method : join() (0) | 2022.07.29 |
[Java] Priority Thread (0) | 2022.07.29 |
[Java] Thread (0) | 2022.07.29 |