Java

동기화(synchronized)

KJihun 2023. 5. 30. 16:24
728x90

멀티 쓰레드의 경우, 자원을 공유하여 작업하기에 장애나 버그가 발생할 수 있다.

이러한 일을 방지하기 위한 방법이 동기화(synchronized)이다.

 

synchronized(동기화)란?

한 쓰레드가 진행중인 작업을 다른 쓰레드가 침범하지 못하도록 막는 것이다.

동기화를 하려면 다른 쓰레드의 침범을 막아야하는 코드들을 '임계영역'으로 설정하여야 한다.

  • 임계영역 : Lock을 가진 단 하나의 쓰레드만 출입이 가능한 영역

 

동기화 방법

1. 실행할 메서드 앞에 synchronized를 붙여 임계영역을 지정한다.

public synchronized void asyncSum() {
	//코드 구현 ....
    }

 

2. 실행할 코드 묶음 앞에 synchronized를 붙여 임계영역을 지정한다.

synchronized(해당 객체의 참조변수) {
	//코드 작성... 
    }

 

사용법 예제

public class Main {
  public static void main(String[] args) {
  
  	//아래에 정의한 AppleStore을 객체로 생성
    AppleStore appleStore = new AppleStore();


    Runnable task = () -> {
    
      //AppleStore의 사과 갯수가 0개가 될때까지 사과를 먹음
      while (appleStore.getStoredApple() > 0){
        appleStore.eatApple();
        System.out.println("남은 사과의 수 = " + appleStore.getStoredApple());
      }
    };

	//쓰레드 3개를 동시에 생성 후 실행
    for(int i = 0; i < 3; i++){
      new Thread(task).start();
    }
  }
}
class AppleStore{
	//사과 갯수
  private int storedApple = 10;

  public int getStoredApple(){
    return this.storedApple;
  }

	//synchronized 메서드 작성
    //작성하지 않을 시, 위의 3개의 쓰레드가 동시에 접근이 가능
    //사과가 한개 남았을 때, 3개의 쓰레드가 접근했다면, -2가 될때까지 먹음
  public synchronized void eatApple(){
    if(getStoredApple() > 0){
      try {
        Thread.sleep(1000);
      }catch (InterruptedException e){
        e.printStackTrace();
      }
      storedApple -= 1;
    }
  }
}