쓰레드의 동기화(Synchronized)

Shin·2022년 12월 9일
0

Java

목록 보기
6/6

🔰 동기화(synchronized)

하나의 쓰레드가 특정 작업을 마치기 전까지 다른 쓰레드에 의해 방해받지 않도록 처리하는 방법

이를 이해하기 위해선 두 가지 개념을 접근해야 한다.

1. Critical Section(임계영역)

critical section, 임계영역 혹은 공유변수 영역이라고도 부르는 개념은 병렬처리가 이루어지는 프로그래밍에서 멀티쓰레드(둘 이사의 쓰레드)가 동시에 데이터를 다루어서는 안되는 공유 자원(공용객체, 파일, 입출력, 데이터)에 접근하는 코드를 의미한다.

class Account {
	private long balance;
	//모든 쓰레드가 공유해서 사용하게 되는 공유객체
}

public void withDraw(){
	
    // 이 부분들은 각 쓰레드별로 병렬로 처리되지만
    
    synchronized (Account) {
    	
        if(balance >= money) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
				}
				balance -= money;
			}
        // 임계영역, 공유변수 영역에 해당하는
        // synchronized block 에서는 
        // 매개변수로 입력한 공유객체에 한해서는
        // 동기화처리를 시행한다.
    
    }
    
}

영화관 예매를 하는 프로그램에서 A라는 고객(쓰레드)이 a-1 이라는 좌석 예매를 시도하는 순간 또다른 B라는 고객(쓰레드)가 똑같은 a-1이라는 좌석 예매를 시도한다면, a-1 좌석은 애매가 된 좌석인지 빈 좌석인지 예측할 수 없다.
이러한 문제들로 인해 멀티쓰레드 환경에선 동기화 처리를 반드시 해주어야 한다. 그리고 임계영역에서 실행되는 쓰레드는 monitor, lock를 획득하게 되고, 단 하나의 쓰레드만이 lock를 획득하고 이외의 쓰레드는 대기를 하게 된다. 이를 통해 마치 순차처리와 같은 모습을 띄게 된다.

2. Lock (혹은 monitor)

자바의 메모리 구조에서 heap 영역에 있는 객체는 모든 쓰레드에서 공유하며 사용이 가능하다. 따라서 멀티쓰레드 환경에서 같은 객체를 사용하다보면 의도치않은 데이터 오류가 발생할 가능성이 있다.

자바에서 모든 객체는 monitor라는 것을 가지고 있다. monitor는 여러 쓰레드가 동시에 객체로 접근하는 것을 막는다.

하나의 쓰레드에서 heap 영역에 있는 객체를 다루는 순간, 해당 쓰레드는 monitor를 획득한다. 쓰레드가 monitor를 획득하면 그 객체에 대해서 lock를 걸 수 있게 된다.
lock이 걸린 객체에 대해서 다른 쓰레드는 해당 객체에 접근할 수 없게 된다.

synchronized 메소드 혹은 synchronized block 를 사용하게 되면, 쓰레드는 object's lock pool로 이동된다.

그 곳에서 공유객체를 사용하는 복수의 쓰레드들 중 공유객체의 monitor를 획득한 하나의 쓰레드는 running 상태로 전이되고, 이 외의 쓰레드들은 Object Lock Pool 안에서 Block 당한다.

monitor를 획득한 쓰레드가 running 하는 과정에서 wait() 이라는 메소드를 호출할 수 있다.
wait()을 호출한 Thread는 object'swiat pool 로 들어간 뒤 block 처리가 된다. 이를 통해 공유객체의 monitor를 놓게 되고, 기존에 lock pool 안에 있던 block된 쓰레드가 monitor를 획득한 뒤 running 상태로 돌아간다.

한편 wait() 메소드로 인해 wait pool로 들어가 block 처리된 쓰레드들은 특정 메소드를 사용하지 않는 이상 해당 풀 안에서 block 처리된 채 유지된다.
따라서 이를 풀어주기 위한 메소드가
notify(쓰레드), notifyAll() 메소드이다.

notify()를 사용한 쓰레드는 runnable 상태로 돌아가고,
notifyAll()를 사용하게 되면 wait pool 내에 있는 모든 쓰레드가 runnable 로 돌아가게 된다.

0개의 댓글

관련 채용 정보