컴퓨터공학 💻 도서관📚

Part2. 6-22 멀티 Thread 프로그래밍에서의 동기화 본문

✅🌲강의 복습 노트/패캠 JavaSpring 강의,코드 복습

Part2. 6-22 멀티 Thread 프로그래밍에서의 동기화

들판속초록풀 2025. 12. 25. 17:20

critical section 과 semaphore

  • critical section 은 두 개 이상의 thread가 동시에 접근 하는 경우 문제가 생길 수 있기 때문에 동시에 접근할 수 없는 영역
  • semaphore 는 특별한 형태의 시스템 객체이며 get/release 두 개의 기능이 있다.
  • 한 순간 오직 하나의 thread 만이 semaphore를 얻을 수 있고, 나머지 thread들은 대기(blocking) 상태가 된다.
  • semaphore를 얻은 thread 만이 critical section에 들어갈 수 있다.

노란색 부분이 critical section 이다.
일종의 열쇠 자물쇠가 있어서 세마포를 가진 스레드만이 critical section에 진입할 수 있다.

critical section 영역은 일종의 메서드가 될 수도 있는데
이 메서드가 공유 자원(임계 영역)을 사용하는 곳인 것이다.

이 부분의 수행을 일종의 열쇠 역할을 하는 세마포를 겟을 해서 이 영역으로 들어간 후 잠군다
나머지 쓰레드들은 대기상태(Block 상태)가 된다. 그 후 다 끝나면 다음 쓰레드가 들어간다.

밑에 코드에서 쓰레드는 Park , ParkWife 이렇게 2개이고
공유 자원은 Bank 클래스(money 멤버변수)이다.
그리고 이 값에 대한 연산이 진행되는 부분은 saveMoney , minusMoney 라는 메서드들이다.

이게 바로 critical section 이다. (임계 영역)

 

sleep 메서드는 Thread의 static 메서드여서  클래스이름으로 참조하면 된다.  Thread.sleep();

 

saveMoney 와 minusMoney 에  synchronized 를 해줘야 오류가 나지 않는다.

그래서 공유 자원에 대한 다른 메서드들의 접근을 막는다

 

 

  • Park 과 ParkWife 가 동시에 Bank 자원에 접근하여 작업이 이루어지는 경우의 예제
class Bank{
	
	private int money = 10000;
	
	public synchronized  void saveMoney(int save){
		
		int m = this.getMoney();
		
		try {
			Thread.sleep(3000);             // 3초 , 1000이 1초
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		setMoney( m + save);
	}
	
	public synchronized  void minusMoney(int minus){
		
		
			int m = this.getMoney();
			
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			setMoney( m - minus);
			
			
	}
	
	public int getMoney(){
		return money;
	}
	
	public void setMoney(int money){
		this.money = money;
	}
}

class Park extends Thread{
	
	public  void run(){
		System.out.println("start save");
		SyncMain.myBank.saveMoney(3000);
		System.out.println("saveMoney(3000): " + SyncMain.myBank.getMoney() );	
	}
}

class ParkWife extends Thread{
	
	public void run(){
		System.out.println("start minus");
		SyncMain.myBank.minusMoney(1000);         // myBank 는 static 참조변수
		System.out.println("minusMoney(1000): " + SyncMain.myBank.getMoney() );
		
	}
	
}

public class SyncMain {
 
	public static Bank myBank = new Bank();     // static 참조변수
	
	public static void main(String[] args) throws InterruptedException {
		
		Park p = new Park();
		p.start();
		
		Thread.sleep(200);
		
		ParkWife pw = new ParkWife();
		pw.start();
	}

}

동기화 (synchronization)

  • 두 개의 thread 가 같은 객체에 접근 할 경우, 동시에 접근함으로써 오류가 발생
  • 동기화는 임계영역에 접근한 경우 공유자원을 lock 하여 다른 thread의 접근을 제어
  • 동기화를 잘못 구현하면 deadlock에 빠질 수 있다.

자바에서는 1. synchronized 메서드나  2. synchronized 블럭을 사용

synchronized 블럭

  • 현재 객체(this) 또는 다른 객체를 lock으로 만든다.
  • 동기화 블럭 ( ) 안에다가 객체를 넣는다
    동기화 블럭이 있는 메서드가 수행되는 동안 
    ( ) 안에 있는 객체에 Lock 을 걸어라 라는 뜻이다.
    이 객체를 다른 메서드가 사용하지 못하게 한다
synchronized(참조형 수식) {  // 참조형 수식은 주로 객체 변수

      수행문;
}

synchronized 메서드

  • 객체의 메소드에 synchronized 키워드 사용
  • 현재 이 메서드가 속해있는 객체에 lock을 건다.
  • 자바에서는 deadlock을 방지하는 기술이 제공되지 않으므로 되도록이면 synchronized 메서드에서
    다른 synchronized 메서드는 호출하지 않도록 한다.
  • deadlock의 예  (deadlock : 두 쓰레드가 서로가 끝나야 수행이 진행될 수 있는데  둘 다 안 끝나는 경우)
    이 경우 쓰레드를 그냥 종료시켜야 한다.  deadlock 상황은 피해야 한다.

Comments