본문 바로가기

Java 공부/신용권의 이것이 자바다

스레드(Thread)에서 동기화(Synchronized) 메소드와 동기화 블럭

반응형


멀티스레드작업을 실행하는 데 있어서 한 스레드가 작업을 하는 동안 다른 스레드가 변경할 수 없도록, 스레드 작업이 끝날 때까지 객체에 잠금을 걸어서 다른 사용할 수 없도록 하는 것이 필요하다.

이렇게 멀티스레드 프로그램에서 단 하나의 스레드만 실행할 수 있는 코드 영역을 임계영역(critical section)이라고 한다.

Java에서는 임계영역을 지정하기 위해 '동기화(Synchronized) 메소드'와 '동기화 블럭'을 사용한다.

이들이 선언되면, 객체에 잠금을 걸어서 다른 스레드가 임계영역 코드를 실행하지 못하도록 한다.

먼저, 동기화가 선언되지 않았을 때의 멀티스레드 작업을 살표보자.

먼저, 스레드 두 개를 사용할 때 각각 2초의 일시 정지 상태를 가진 뒤, 다시 작업을 실행해 그 메모리값을 출력하는 클래서를 만들자. 



이제는 이 스레드 작업을 공유하는 객체를 만든다.

이를 위해서 각각 User1과 User2객체를 만들었다.



User1의 메모리 값은 100을 설정했다.



그리고 User2는 메모리값을 50을 주었다.



그러고 나서 '동기화하지 않은'( Unsynchronized) 상태로 메인클래스를 작성했다.

이 작업을 수행한 후, 콘솔창에 나온 결과를 보자!

User2가 작업을 수행한 후에 User1의 값 100이 50으로 변한 걸 볼 수 있다.

User2의 값 50으로 User1의 값이 변한 것이다.

이것을 방지하기 위해, 동기화 메소드나 동기화 블럭을 건다.


동기화메소드를 작성하는 것은 간단하다.

앞의 Calculator라고 이름붙인 공유객체의 메소드에 동기화(Synchronized)를 선언해주면 된다.

알 동그라미친 부분만 첨가하면, 동기화(Synchronized) 메소드로 변환된 것이다. 



이제, 메인 클래스를 실행해 보자!



위 콘솔창을 바면, User1의 메모리 값이 그대로 100으로 찍힌 것을 확인할 수 있을 것이다.

한편, 동기화 블럭은 여러 가지 스레드가 실행 가능한 메소드 안에 동기화 블럭을 넣는 것이다.

동기화 블럭 코드는 다음과 같다.

public void method()  {

   ....

   synchronized(공유객체) {

   }

}

위 메소드에서는 여러 스레드가 동시에 실행할 수 있지만, 동기화 블럭의 영역은 임계영역으로 설정되어, 한번에 하나의 스레드만 실행되는 것이다. 

이처럼 동기화 메소드나 동기화 블럭에서는 먼저 접근한 객체의 작업이 끝날 때까지 다른 객체가 공유한 객체에 접근할 수 없다.

그러나 동기화를 걸지 않은 일반 메소드에는 접근이 가능하다.



반응형