본문 바로가기

JAVA/자바 스레드 기초

04. 스레드 동기화

스레드 동기화의 필요성

멀티스레드 프로그램이 실행될 때, 다수의 스레드가 공유 데이터를 동시에 접근하는 경우가 발생한다. 특히 다수의 스레드가 동시에 공유 데이터의 값을 변경시키는 경우, 공유 데이터의 값이 정상적으로 변경되지 않는다. 공유 데이터를 동시 접근하는 여러 스레드에 의해 공유 데이터의 값이 비정상적으로 유지되지 않도록 스레드의 실행을 제어하는 기술을 스레드동기화(thread synchronization)라고 부른다. 자바의스레드 동기화에는 2가지 방법이 있다.

1) synchronized로 동기화 블록 지정

2) wait() - notify() 메소드로 스레드 실행 순서 제어

멀티스레드의 동시접근을 순차화하면 출력이 섞이는 문제를 해결할 수 있다. 

 

자바 스레드 동기화를 위한 synchronized 블록

가장 쉬운 스레드 동기화 기법은, 스레드가 공유 데이터를 접근할 때, 하나씩 순차적으로 실행하도록 제어하는 기법이다. 한 스레드가 공유 데이터의 접근을 시작한 순간, 열쇠로 잠가(lock) 다른 스레드가 공유 데이터를 접근하지 못하게 하는 것이다.

    synchronized 키워드는 스레드 동기화를 위한 장치로서, 코드 블록을 동기화가 설정된 임계 영역으로 지정한다. 메소드를 임계 영역으로 지정하는 방법과 임의의 코드 블록만 지정하는 두 가지 방법이 있다. 자바 플랫폼은 한 스레드가 synchronized 블록에 진입하면, 자동으로 lock을 걸어서 synchronized 블록을 실행하고자 하는 다른스레드는 lock이 풀릴 때까지 대기하도록 한다.

 

wait() - notify()를 이용한 스레드 동기화

스레드들이 순차적으로 공유 데이터에 접근하도록 제어된 경우여도, 여전히 동기화를 해야하는 상황이 있다. 한개의 공유 데이터를 통해 두 스레드가 데이터를 주고받을 때, 두 스레드 사이의 충돌을 해결하는 producer-consumer 문제이다. 예를 들어 비디오 스트리밍 소프트웨어는 네트워크 서버로부터 압축된 비디오 프레임을 주기적으로 가지고 와서 비디오 버퍼에 저장하는 입력스레드(producer)와 비디오 버퍼에 들어있는 비디오 프레임을 디코딩하여 화면에 출력하는 재생스레드(consumer)로 구성된다.  이때 만일 네트워크의 속도가 갑자기 떨어져서 입력스레드의 공급이 일시적으로 늦어지게 되면, 재생 스레드는 버퍼가 다 찰때까지 기다리게(wait)된다. 잠시 후 입력 스레드가 버퍼에 비디오 프레임을 공급하고 대기중인 재생 스레드를 깨운다(notify). 반대로 네트워크 속도가 순간적으로 빨라져서 입력스레드가 채운 버퍼를 재생 스레드가 미처 소비하지 못한 경우에는, 입력 스레드는 비디오 버퍼가 비워지기를 기다린다(wait). 잠시 후 재생 스레드는 버퍼를  소비하고 나서 버퍼가 비워지기를 기다리는 입력 스레드를 깨운다(notify). wait()-notify()를 이용하면 producer-consumer 문제의 스레드 동기화를 해결할 수 있다.

    입력 스레드와 재생 스레드가 대기하는 비디오 버퍼를 동기화 객체라고 부른다. 자바는 모든 객체가 동기화 객체가 될 수 있도록 설계하였다. 모든 객체는 Object 클래스를 상속받으며, Object 클래스는 wait()와 notify() 메소드를 가지고 있기 때문이다. 

'JAVA > 자바 스레드 기초' 카테고리의 다른 글

03. 스레드 종료  (0) 2024.03.13
02. 자바 스레드 만들기  (0) 2024.03.13
01. 멀티태스킹  (0) 2024.03.13