Java

134. 쓰레드의 동기화 - 패스트캠퍼스 백엔드 부트캠프 3기

gkss2tpt 2025. 1. 7. 16:13

1. 쓰레드의 동기화(synchronization)

  • 한 쓰레드가 진행중인 작업을 다른 쓰레드가 간섭하지 못하게 막는 것
  • 진행중인 작업이 다른 쓰레드에게 간섭받지 않게 하려면 '동기화'가 필요
  • 멀티 쓰레드 프로세스에서는 다른 쓰레드의 작업에 영향을 미칠 수 있다.
  • 동기화하려면 간섭받지 않아야 하는 문장들을 '임계 영역'으로 설정
  • 임계영역은 락(lock)을 얻은 단 하나의 쓰레드만 출입가능(객체 1개에 락 1개)

2. synchronized를 이용한 동기화

  • synchronized로 임계영역(lock이 걸리는 영역)을 성정하는 방법 2가지
1. 메서드 전체를 임계 영역으로 지정
public synchronized void calcSum() {
    //...
}

2. 특정한 영역을 임계 영역으로 지정
synchronized(객체의 참조변수) {
    //...
}

1)
public synchronized void withdraw(int money) {
    if(balance >= money) {
        try {
            Thread.sleep(1000);
        } catch(Exception e) {}
        
        balance -= money;
    }
}

2)
public synchronized void withdraw(int money) {
    synchronized(this) {
    	if(balance >= money) {
            try {
                Thread.sleep(1000);
            } catch(Exception e) {}
        
            balance -= money;
        }
    }	// synchronized(this)
}

 

3. 예제

public class Ex_01 {
    public static void main(String[] args) {
        Runnable r = new RunnableEx22();
        new Thread(r).start();
        new Thread(r).start();
    }
}

class Account2 {
    private int balance = 1000; // private으로 해야 동기화 의미가 있다.

    public synchronized int getBalance() {
        return balance;
    }

    public synchronized void withdraw(int money) {  // synchronized 동기화
        if (balance >= money) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e){}
            balance -= money;
        }
    } // synchronized
}

class RunnableEx22 implements Runnable {
    Account2 acc = new Account2();

    public void run() {
        while (acc.getBalance() > 0) {
            // 100, 200, 300중 한 값을 임의로 선택해서 출금(withdraw)
            int money = (int)(Math.random()*3+1) * 100;
            acc.withdraw(money);
            System.out.println("balance"+acc.getBalance());
        }
    }
}