Java/자바 정리

133. 스레드 충돌 막기 – synchronized로 동기화 처리

코딩하는냥이 2025. 5. 19. 12:53
반응형

멀티스레드 환경에서는 여러 스레드가 하나의 객체에 동시에 접근하게 되면,
데이터가 뒤섞이거나 원하는 결과가 출력되지 않는 문제가 발생할 수 있습니다.
이러한 문제를 방지하기 위해 synchronized 키워드를 사용하면,
동시에 하나의 스레드만 메서드에 접근하도록 제한할 수 있어 안전한 동작을 보장할 수 있습니다.


📦 Calculator.java

package ch14.sec06;

public class Calculator {
	private int memory;

	public int getMemory() {
		return memory;
	}

	public void setMemory(int memory) {
		this.memory = memory;
	}
	
	public synchronized void setMemory1(int memory) {
		setMemory(memory);
		try {Thread.sleep(2000);} catch (Exception e) {}
		System.out.println(Thread.currentThread().getName()+": " + this.memory);
	}
	
	public synchronized void setMemory2(int memory) {
		setMemory(memory);
		try {Thread.sleep(2000);} catch (Exception e) {}
		System.out.println(Thread.currentThread().getName()+": " + this.memory);
	}
}

📦 User1Thread.java

package ch14.sec06;

public class User1Thread extends Thread{
	private Calculator calculator;

	public void setCalculator(Calculator calculator) {
		this.calculator = calculator;
	}
	
	public User1Thread() {
		setName("User1Thread");
	}
	
	public void run() {
		calculator.setMemory1(100);
	}
}

📦 User2Thread .java

package ch14.sec06;

public class User2Thread extends Thread{
	private Calculator calculator;

	public void setCalculator(Calculator calculator) {
		this.calculator = calculator;
	}
	
	public User2Thread() {
		setName("User2Thread");
	}
	
	public void run() {
		calculator.setMemory2(50);
	}
}

📌 예제 코드

package ch14.sec06;

public class SynchronizedExample {
	public static void main(String[] args) {
		Calculator calculator = new Calculator();
		
		User1Thread user1Thread = new User1Thread();
		User2Thread user2Thread = new User2Thread();
		
		user1Thread.setCalculator(calculator);
		user2Thread.setCalculator(calculator);
		
		user1Thread.start();
		user2Thread.start();
	}
}

💻 실행 결과

User1Thread: 100
User2Thread: 50

※ 스레드 실행 순서는 상황에 따라 달라질 수 있습니다. 하지만 synchronized 덕분에
데이터가 뒤섞이지 않고 안전하게 출력됩니다.

※ 실행 순서는 상황에 따라 다를 수 있지만, 두 스레드가 서로 영향을 주지 않고 순차적으로 출력되는 것을 확인할 수 있습니다.


💬 코드 설명

  • Calculator 클래스에는 setMemory1()이라는 메서드가 있으며, 이 메서드에는 synchronized 키워드가 붙어 있습니다.
  • synchronized가 붙은 메서드는 한 번에 하나의 스레드만 접근할 수 있기 때문에,
    User1Thread가 setMemory1()을 실행하는 동안에는 User2Thread는 대기하게 됩니다.
  • Thread.sleep(2000)을 사용하여 작업을 일부러 지연시킴으로써,
    스레드 충돌 없이 순차적으로 처리되는 결과를 관찰할 수 있도록 구성되어 있습니다.

💡 포인트 정리

  • synchronized는 멀티스레드 환경에서 공유 자원에 동시에 접근하는 것을 방지합니다.
  • 한 번에 하나의 스레드만 메서드를 실행할 수 있도록 하여, 데이터의 일관성과 안정성을 유지할 수 있습니다.
  • 공유 객체가 있을 때는 항상 동기화를 고려해야 합니다.

📌정리하자면, synchronized는 멀티스레드 프로그래밍에서 가장 기본적이면서도 중요한 동기화 수단입니다.
여러 스레드가 하나의 메서드나 자원에 동시에 접근하지 않도록 막아주어
스레드 간의 충돌이나 데이터 손상을 방지할 수 있습니다.
이번 예제를 통해 synchronized가 적용된 경우와 그렇지 않은 경우의 차이를 명확하게 이해하셨으면 좋겠습니다.