네, 가능합니다. Java에서 run() 메서드를 synchronized 키워드로 선언하는 것은 문법적으로 아무런 문제가 없습니다. 하지만 대부분의 경우 동기화가 필요하지 않은데, 그 이유는 run() 메서드가 각 스레드에 의해 한 번씩만 실행되기 때문입니다. 즉, run() 메서드 자체에는 별도의 동기화(synchronization)가 요구되지 않습니다.
반면, 하나의 인스턴스를 여러 스레드가 동시에 공유하며 호출하는 다른 클래스의 인스턴스(비정적) 메서드에는 동기화를 적용하는 것이 좋은 습관입니다. 이러한 메서드는 여러 스레드가 동시에 접근할 경우 데이터 불일치나 경쟁 상태(race condition)가 발생할 수 있기 때문입니다.
예제 코드
public class SynchronizeRunMethodTest implements Runnable {
public synchronized void run() {
System.out.println(Thread.currentThread().getName() + " is starting");
for(int i=0; i < 5; i++) {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " is running");
} catch(InterruptedException ie) {
ie.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " is finished");
}
public static void main(String[] args) {
SynchronizeRunMethodTest test = new SynchronizeRunMethodTest();
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
t1.start();
t2.start();
}
}실행 결과
Thread-0 is starting Thread-0 is running Thread-0 is running Thread-0 is running Thread-0 is running Thread-0 is running Thread-0 is finished Thread-1 is starting Thread-1 is running Thread-1 is running Thread-1 is running Thread-1 is running Thread-1 is running Thread-1 is finished
결과 분석
위 실행 결과에서 주목할 점은 두 스레드가 교차로 실행되지 않고, Thread-0이 모든 작업을 마친 후에야 Thread-1이 시작된다는 것입니다. 이는 run() 메서드가 synchronized로 선언되어 있고, 두 스레드(t1, t2)가 동일한 인스턴스(test)를 공유하기 때문입니다. synchronized 메서드는 해당 객체의 모니터 락(lock)을 사용하므로, 한 스레드가 락을 점유하고 실행하는 동안 다른 스레드는 대기 상태에 있게 됩니다.
만약 run() 메서드에서 synchronized 키워드를 제거하면, 두 스레드의 출력이 서로 뒤섞여 나타나는 것을 확인할 수 있습니다. 이처럼 공유 객체를 기반으로 여러 스레드가 동일한 메서드를 실행할 때는 동기화가 실행 순서와 데이터 일관성을 보장하는 중요한 역할을 합니다.