[Java] Thread의 동기화

클라우드·2024년 4월 8일
0

Java

목록 보기
12/20
post-thumbnail

8. Thread의 동기화


  • Monitor : Thread가 획득할 수 있는 자격
  • Thread → Runnable → 공용 객체
package test;

// 공유 자원 한 가지 정의
// Thread에 의해서 같이 사용되는 자원
// 즉, 공유 객체를 만들어서 사용한다.
// 공유 객체를 만들려면 당연히 class가 있어야 한다.
class Account {
    private int balance = 1000; // 잔액

    // 잔액 알아오는 method
    public int getBalance() {
        return balance;
    }

    // 출금하는 method
    // synchronized 키워드는 하나의 Thread가 이 메소드를 쓰면
    // 다른 Thread는 block이 걸리면서 순차적으로 처리가 된다.
    // Critical Section 임계 영역이 생긴다.
    // 임계 영역을 설정해서 다수의 Thread가 동시에 사용할 수 없도록
    // synchronized 키워드로 임계 영역을 설정한다.
    // 당연히 순차 처리가 된다.
    // 그러나 method에 이 키워드를 사용하는게 부담스럽다.
    // 이 method 안에 모든 코드들이 동기화를 필요로 하는 것이 아니기 때문에
    // 따라서 일반적으로 synchronized block을 이용한다.
    public synchronized void withdraw(int money) {
        if (balance > money) {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {

            }
//            synchronized (this) { // 임계 영역을 줄여서 훨씬 효율적으로 synchronized를 사용한다.
//                balance -= money;
//            }
            balance -= money;
        }
    }

}

// Thread → Runnable → 공용 객체
class MySyncRunnable implements Runnable {

    Account acc = new Account(); // 공용 객체
    @Override
    public void run() {
        while(acc.getBalance() > 0) {
            int money = (int)(Math.random() * 3 + 1) * 100;
            acc.withdraw(money);
            System.out.println("잔액은 " + acc.getBalance());
        }
    }
}

public class ThreadSyncTest {
    public static void main(String[] args) {
        MySyncRunnable r = new MySyncRunnable();

        // 같은 Runnable 객체를 다른 Thread가 사용
        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);

        t1.start();
        t2.start();
    }
}


package test;

class Shared {

    // method 1개 만든다.
    // 해당 공유 객체는 여러 Thread에 의해서 같이 사용되는데
    // method를 호출할 때는 동기화시켜서 사용한다.
    public synchronized void printNum() {
        try {
            for (int i=0; i<10; i++) {
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + ":" + i);
                notify(); // 아까 전의 Thread를 깨운다.
                wait();
            }
        } catch (Exception e) {

        }
    }
}

class MyRunnable_10 implements Runnable {

    private Shared shared;

    public MyRunnable_10(Shared shared) {
        this.shared = shared;
    }

    @Override
    public void run() {
        shared.printNum();
    }
}

public class ThreadWaitNotiTest {
    public static void main(String[] args) {
        Shared obj = new Shared(); // 공유 객체

        Thread t1 = new Thread(new MyRunnable_10(obj));
        Thread t2 = new Thread(new MyRunnable_10(obj));

        t1.setName("첫 번째 Thread");
        t2.setName("두 번째 Thread");

        t1.start();
        t2.start();
    }
}
  • 상태 전이도 전체적인 그림
profile
안녕하세요 :)

0개의 댓글