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메서드 사용 가능 )

 

한 번의 한개의 스레드만 들어올 수 있다.