Java에서 synchronized 키워드는 멀티스레딩 환경에서 동기화 (Synchronization) 를 보장하기 위해 사용됩니다. 동기화를 통해 여러 스레드가 동시에 공유 자원에 접근하는 것을 방지하고, 데이터의 일관성을 유지할 수 있습니다. 이번 글에서는 synchronized 키워드의 개념, 사용법, 적용 방법 및 주의할 점을 살펴보겠습니다.
1. synchronized 키워드란?
멀티스레드 환경에서는 여러 스레드가 동시에 실행되므로, 공유 자원(Shared Resource)에 대한 동기화가 필요할 수 있습니다. synchronized 키워드를 사용하면 한 번에 하나의 스레드만 특정 코드 블록을 실행할 수 있도록 제한할 수 있습니다.
synchronized의 주요 기능
- 한 번에 하나의 스레드만 특정 블록 실행 가능
- 공유 자원의 일관성 유지
- 데드락(Deadlock) 및 성능 저하 가능성 존재
2. synchronized의 사용법
2.1 메서드 동기화
메서드 전체를 동기화할 때 synchronized 키워드를 사용합니다.
예제: 동기화된 메서드
class SharedResource {
synchronized void printMessage(String message) {
for (int i = 0; i < 5; i++) {
System.out.println(message + " - " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread extends Thread {
SharedResource resource;
String message;
MyThread(SharedResource resource, String message) {
this.resource = resource;
this.message = message;
}
public void run() {
resource.printMessage(message);
}
}
public class SynchronizedMethodExample {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
MyThread t1 = new MyThread(resource, "Thread 1");
MyThread t2 = new MyThread(resource, "Thread 2");
t1.start();
t2.start();
}
}
실행 결과 (스레드가 순차적으로 실행)
Thread 1 - 0
Thread 1 - 1
Thread 1 - 2
Thread 1 - 3
Thread 1 - 4
Thread 2 - 0
Thread 2 - 1
Thread 2 - 2
Thread 2 - 3
Thread 2 - 4
🚀 동기화 덕분에 한 번에 하나의 스레드만 실행되므로, 두 개의 스레드가 순차적으로 실행됩니다.
2.2 블록 동기화
메서드 전체가 아니라, 특정 블록만 동기화할 수도 있습니다. 이 방법을 사용하면 불필요한 코드 블록까지 동기화하지 않아서 성능을 향상시킬 수 있습니다.
예제: 동기화된 블록
class SharedResource {
void printMessage(String message) {
synchronized (this) { // 특정 블록만 동기화
for (int i = 0; i < 5; i++) {
System.out.println(message + " - " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
✅ 특정 블록만 동기화하여 필요한 부분만 보호할 수 있습니다.
3. 정적 메서드 동기화
클래스 레벨에서 동기화를 적용하려면 synchronized를 정적 메서드에 사용할 수 있습니다. 이 경우, 클래스 자체에 대한 락(lock)이 걸리므로, 모든 인스턴스에서 하나의 스레드만 실행됩니다.
예제: 정적 메서드 동기화
class SharedResource {
synchronized static void staticMethod(String message) {
for (int i = 0; i < 5; i++) {
System.out.println(message + " - " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread extends Thread {
public void run() {
SharedResource.staticMethod(Thread.currentThread().getName());
}
}
public class StaticSyncExample {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.start();
t2.start();
}
}
✅ 모든 인스턴스에서 동기화가 적용되므로, 클래스 자체에 대한 락이 걸립니다.
4. synchronized 사용 시 주의할 점
4.1 성능 문제
- synchronized 키워드를 사용하면 스레드 간 동기화가 발생하므로 성능 저하가 발생할 수 있습니다.
- 필요하지 않은 경우 동기화를 최소화해야 합니다.
4.2 데드락(Deadlock) 문제
- 여러 개의 스레드가 서로 다른 자원을 점유하면서 상대방이 점유한 자원의 해제를 기다리는 경우 데드락이 발생할 수 있습니다.
- 다중 락을 사용할 때 주의해야 합니다.
5. 결론
- synchronized 키워드는 멀티스레드 환경에서 공유 자원의 동기화를 보장합니다.
- 메서드 동기화, 블록 동기화, 정적 메서드 동기화 방법이 있으며, 필요한 부분만 동기화하여 성능을 최적화해야 합니다.
- 잘못된 사용은 성능 저하 및 데드락을 유발할 수 있으므로 신중하게 적용해야 합니다.
'java' 카테고리의 다른 글
| List 에 관하여 (0) | 2025.02.10 |
|---|---|
| DTO, VO, DAO 에 관하여 (0) | 2025.02.06 |
| 접근 제한자에 관하여 (1) | 2025.02.04 |
| 정적 바인딩과 동적 바인딩에 관하여 (0) | 2025.02.04 |
| Java 상속에 관하여 (0) | 2025.02.03 |