본문 바로가기

Programming/JAVA

멀티 스레드(4) - 동기화 메서드와 동기화 블록 3

JAVA logo image

 

 

 

앞선 아티클에서 동기화(synchronized) 메서드/블록 선언을 배웠습니다. 이제 우리가 이전에 작성했던 Calculator 예제를 수정해서 동기화 메서드/블록을 실습해 보겠습니다. 

 

앞선 아티클에서 작성했던 코드를 다시 살펴보겠습니다. 

 

// Calculator.java
public class Calculator {
	private int memory;
	
	public int getMemory() {
		return memory;
	}
	
	public void setMemory(int memory) {
		this.memory = memory;
		try {
			Thread.sleep(2000);
		} catch(InterruptedException e) {}
		System.out.println(Thread.currentThread().getName() + ": " + this.memory);
	}
}

 

 

// User1.java
public class User1 extends Thread {
	private Calculator calculator;
	
	public void setCalculator(Calculator calculator) {
		this.setName("User1");
		this.calculator = calculator;
	}
	
	public void run() {
		calculator.setMemory(100);
	}
}

 

// User2.java
public class User2 extends Thread {
	private Calculator calculator;
	
	public void setCalculator(Calculator calculator) {
		this.setName("User2");
		this.calculator = calculator;
	}
	
	public void run() {
		calculator.setMemory(50);
	}
}

/* 출력
User1: 50
User2: 50
*/

 

// ExampleMain.java
public class ExampleMain {
	public static void main(String[] args) {
		Calculator calculator = new Calculator();
		
		User1 user1 = new User1();
		// 공유객체 설정
		user1.setCalculator(calculator);
		user1.start();
		
		User2 user2 = new User2();
		// 공유객체 설정
		user2.setCalculator(calculator);
		user2.start();
	}
}

/* 출력
User1: 50
User2: 50
*/

 

 

 


 

 

 

위의 코드 중에서 Calculator.java를 아래와 같이 수정합니다. 

 

// Calculator.java
public class Calculator {
	private int memory;
	
	public int getMemory() {
		return memory;
	}
	
	public synchronized void setMemory(int memory) {
		this.memory = memory;
		try {
			Thread.sleep(2000);
		} catch(InterruptedException e) {}
		System.out.println(Thread.currentThread().getName() + ": " + this.memory);
	}
}

 

 

그리고나서 ExampleMain.java에서 프로그램을 실행하면, 기존 예제와 달리 출력 값은 아래와 같습니다. 

 

/* 출력
User1: 100
User2: 50
*/

 

위에서 User1 스레드는 Calculator 객체의 동기화 메서드 setMemory( )를 실행하는 순간 Calculator 객체를 잠그게 됩니다. 그래서 메인 스레드가 User2를 실행하더라도 setMemory( )를 실행시키지 못하고, User1이 setMemory( )를 실행하는 동안 대기하게 됩니다. 

 

한편, setMemory( )를 동기화 메서드로 만드는 것이 아니라 동기화 블록으로 만드는 것도 가능합니다. 아래와 같이 작성하는 것도 가능합니다. 

 

public class Calculator {
	private int memory;
	
	public int getMemory() {
		return memory;
	}
	
	public void setMemory(int memory) {
		synchronized (this) {
			this.memory = memory;
			try {
				Thread.sleep(2000);
			} catch(InterruptedException e) {}
			System.out.println(Thread.currentThread().getName() + ": " + this.memory);
		}
	}
}

 

해당 예제에서 this는 공유 객체인 Calculator 객체를 의미하게 됩니다. 스레드가 동기화 블록 안으로 들어가면, this인 Calculator 객체를 잠그고 동기화 블록 내용을 실행하게 됩니다.