synchronized
메소드 또는 블록 사용📁 ex01
☕ ATM.java
public class ATM {
private int balance = 0;
public void addMoney(int amount) {
balance += amount;
}
public int getBalance() {
return balance;
}
// 💡 앞에 synchronized를 붙이고 다시 실행해 볼 것
public void withdraw (String name, int amount) {
// 💡 또는 아래 내용을 이 블록으로 옮겨 볼 것
// - this는 현 쓰레드를 의미함
// - 메소드 내의 특정 작업만 동기화가 필요할 때
//synchronized (this) {
//}
if (balance < amount) return;
System.out.printf(
"💰 %s 인출 요청 (현 잔액 %d)%n",
name, balance
);
try {
Thread.sleep(new Random().nextInt(700, 1000));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
balance -= amount;
System.out.printf(
"✅ %s 인출 완료 (현 잔액 %d)%n",
name, balance
);
}
}
☕ CustomerRun.java
public class CustomerRun implements Runnable {
String name;
ATM atmToUse;
int needed;
public CustomerRun(String name, ATM atmToUse, int needed) {
this.name = name;
this.atmToUse = atmToUse;
this.needed = needed;
}
@Override
public void run() {
while (atmToUse.getBalance() > needed) {
atmToUse.withdraw(name, needed);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
☕ Main.java
ATM atm = new ATM();
atm.addMoney(5000);
Thread thr1 = new Thread(
new CustomerRun("철수", atm, 500)
);
Thread thr2 = new Thread(
new CustomerRun("영희", atm, 300)
);
Thread thr3 = new Thread(
new CustomerRun("돌준", atm, 400)
);
thr1.start();
thr2.start();
thr3.start();
📁 ex02
☕ Cache1.java
public class Cache1 {
static boolean stop = false;
public static void main(String[] args) {
new Thread(() -> {
int i = 0;
while (!stop) {
i++;
// ⭐️ 아래를 주석처리하고 다시 실행해보기
System.out.println(i);
}
System.out.println("- - - 쓰레드 종료 - - -");
}).start();
try { Thread.sleep(1000);
} catch (InterruptedException e) {}
stop = true;
// 💡 JVM의 캐시 방식에 따라 멈출 수도 안 멈출 수도 있음
// - stop으로의 접근이 동기화되지 않았을 시
// - 한 쓰레드가 그 값을 바꿔도 다른 쓰레드는 캐시에 저장된
// - 바뀌기 이전 값을 참조할 수 있음
// - println 메소드는 위 코드에서 캐시를 비우는 이유 제공
}
}