스레드의 동기화(Synchronization)
[강이의 자바강좌[쓰레드의 동기화[Synchronization]
]
]
동시 프로그래밍 영역에서 다중쓰레드는 말그대로 어디로 튈지 모르는 공과 같다. 어느 쓰레드가 먼저 작동할런지는 모르지만 이왕 작동했으면 처음부터 끝까지 맡은바 임무(출력 메세지)는 완수하도록 권한을 부여하는 것이 동기화(Synchronization)라 할수 있겠는데 동기화라는 말자체가 어려워서 많이 애먹는것 같다. 필자는 동기화라는 표현보다는 보호막이라는 표현이 synchronization을 이해하는데 더 도움이 될꺼라 생각한다.
자바에서 다중쓰레드가 공유하고 있는 자원을 어떤 쓰레드가 실행하고 있을때 다른 쓰레드는 접근하지 못하도록 막아주는 "보호막" 같은 장치가 바로 synchronized 라는 키워드다. 쓰는 방법은 쓰레드에서 보호막 치기를 원하는 부분을 { } 블록으로 감싸고 그 위에 synchronized(레퍼런스) 라는 타이틀을 만들어주면 된다. 다시 코드로 표현하면 아래와 같이 될것이다.
[강이의 자바강좌]
[Synchronization]
[쓰레드의 동기화]
예제에서는 쓰레드에게 권한을 주는 용도로 쓰일 레퍼런스를 key라고 명하고 Object를 이용해 만들어 쓰고 있는데 이 권한을 같이 공유하면서 서로 쓸수 있도록 만들어야되므로 static을 붙였다. 결과에서 보듯이 한 쓰레드가 key(권한)를 얻어 출력을 시작하면 다른 쓰레드가 출력이 끝날때까지 대기했다가 key(권한)를 넘겨받아 자신이 가진 메세지를 출력하고 남아있는 쓰레드도 역시 출력이 끝날때까지 기다렸다가 본인이 가진 메세지를 key(권한)를 넘겨받은 후에야 출력을 한다. 예제에서는 쓰레드가 3개인 다중쓰레드를 작동하였는데 작업환경에 따라 어느 구문이 먼저 출력될지는 장담할수 없겠지만 어느 쓰레드건 출력을 시작했으면 처음부터 끝까지 그 구문은 완전하게 찍히는 것을 확인할수 있을 것이다.
이렇게 일정 구문을 동기화 시켜서(보호막 만들어서) 사용한다고 하여 동기화 구문(Synchronized Statements)이라고 부른다. 말나온김에 동기화 메소드(Synchronized Methods)도 공부해 보자. 말그대로 메소드앞에 그러니까 메소드 리턴타입앞에 synchronized 키워드를 붙여주면 메소드 전체를 동기화 즉 보호막 만들어서 사용할수 있다.
synchronized void print(String message )
{
...
......
}
이 경우에는 쓰레드가 해당클래스의 객체를 공유하도록 만들어야 정상적으로 작동된다. 이렇게 설명하고 끝내면 비난(?)이 빗발칠걸로 예상되므로 동기화 메소드에 관련된 예제도 아래에 준비하였으니 코드를 보면서 연구해보기 바란다. 결과는 위와 같을 것이나 이번에는 구문이 아닌 메소드를 동기화시켰다는게 차이점이다.
예제를 간략하게 설명하자면 클래스의 레퍼런스로 key를 만들어 쓰레드끼리 공유해서 쓰도록 하고 있고 쓰레드의 실행블록인 run( ) 메소드에서 동기화시킨 print( ) 메소드를 key 레퍼런스를 이용해 불러서 쓰면 특정 쓰레드가 해당블록 실행시 다른 쓰레드가 관련 메소드에 들어오지 못하도록 보호막을 쳐준다. key의 데이터형이 지금 클래스명이라는 것을 여러분이 알아챘기 바란다. 예제를 곰곰히 이리저리 씹어보면 어느순간(?) 이해가 되기 시작할 것이다. 생성자(constructor)를 이용하면 코드가 훨씬 더 간결해질 것이나 이해를 돕고자 기존 예제를 최대한 건드리지 않는 쪽으로 가닥을 잡아서 만든 까닭에 소스가 좀 길다. 마음에 안들면 생성자를 이용해서 여러분이 원하는데로 응용해 보기 바란다.+ 제발 해봐라.ㅎㅎ 또한 synchronized 키워드를 메소드에서 제하고 다시 실행을 하여 무슨 차이가 있는지 비교하기 바란다.^^
쓰레드의 동기화는 동시 프로그래밍 영역에서 매우 유용하게 쓰이는 부분이다. 이보다 더 간단할수는 없다라는 심정으로 쓰레드의 Synchronization에 관한 가장 기본적인 내용만이라도 확실하게 기억하기를 바라면서 본 강좌를 아주 심플하게 구성하였으니 더도 덜도말고 최소한 오늘 배운 내용은 확실하게 습득하기 바란다.^^