Java
Java : 쓰레드의 동기화 (synchronization) - 기초
흰색기린
2021. 8. 11. 21:57
- 멀티 쓰레드 프로세스에서는 다른 쓰레드의 작업에 영향을 미칠 수 있다 !
- 진행중인 작업이 다른 쓰레드에게 간섭을 받지 않으려면 '동기화' 필요
- 동기화하려면 간섭받지 않아야 하는 문장들을 '임계 영역'으로 설정
- 임계 영역은 락(lock)을 얻은 단 하나의 쓰레드만 출입가능(객체 1개에 락 1개)
쓰레드의 동기화 ( ? )
한 쓰레드가 진행중인 작업을 다른 쓰레드가 간섭하지 못하게 막는 것이다.
synchronized로 임계영역(lock이 걸리는 영역)을 설정하는 방법 2가지
//1. 메서드 전체를 임계 영역으로 지정
public synchronized void calcSum(){
// ..
}
//2. 특정한 영역을 임계 영역으로 지정
synchronized(객체의 참조변수){
// ..
}
은행 예제
package ThreadPt;
public class syn1 {
public static void main(String[] args) {
Runnable r = new Runn2();
new Thread(r).start();
new Thread(r).start();
}
}
// 은행
class Account2{
private int balance = 1000; // private으로 해야 동기화가 의미 있음. public이면 접근할 수 있음 ..
public int getBalance() {
return balance;
}
// 출금 하는 동안 출금을 실행시킬수 없으니깐 synchronized로 메서드 동기화 시켰음
public synchronized void withdraw(int money) {
if(balance >= money) {
try {Thread.sleep(1000);}
catch (InterruptedException e) {}
balance -= money;
}
}
}
class Runn2 implements Runnable{
Account2 ac2 = new Account2();
@Override
public void run() {
while(ac2.getBalance() > 0) {
int money = (int)(Math.random()*3 +1) * 100;
ac2.withdraw(money);
System.out.println("잔고 : " + ac2.getBalance());
}
}
}
은행을 만들어서 처음에 은행 잔고에는 1000이 있고
출금을 하는데 랜덤으로 100 , 200 , 300중의 한 값을 임의로 선택해서 출금하는 예제이다.
잔고가 점점 줄어들다가 스레드(일꾼이)이 두명이 와서 출금하는데
잔고가 200원이 남았을때 if(balance >= money)문을 A,B둘다 통과해서
A가 200원을 빼가고 , B도 200원을 빼가면 마이너스가 될 수 있다. ( synchronized 키워드가 없을 때 ! )
지금은 임계영역이 걸려있으므로 (lock) 객체 1개만 들어올 수 있다. ( 출금은 한명만 가능 ! 끝나고 withdraw메서드 사용 가능 )
한 번의 한개의 스레드만 들어올 수 있다.