본문 바로가기

명사 美 비격식 (무리 중에서) 아주 뛰어난[눈에 띄는] 사람[것]

JAVA

synchronized 동기화를 보완하다, wait()과 notify() 락을 가진 상태로 오랜시간 유지하지않도록

앞서 sunchronized로 동기화해서 공유데이터를 보호했다.

https://standout.tistory.com/1428

 

synchronized 를 이용한 스레드의 동기화

스레드의 동기화란. 한 스레드가 특정작업을 끝마치기 전까지 다른 스레드에 의해 방해받지 않도록 하는것. 자바에서는 synchronized블럭을 이용해서 스레드의 동기화를 지원했지만 jsk1.5부터 java.u

standout.tistory.com

 

그러나 특정 스레드가 객체의 락을 가진 상태로 오랜시간 유지하지않도록 하는것도 중요하다.

wait과 notify는 공기화된 임계영역의 코드를 수행하다 작업이 더이상 진행할 상황이 아닐경우, 

일단 wait을 호출하여 스레드가 락을 반납하고 기다리게한다.

이후 작업을 수행할 수 있는 상황이 되면 notify를 호출해 중단했던 락을 다시 얻어 작업을 실행한다.

 

 

 

 

예시코드에서 `SharedObject` 클래스는 공유 객체를 나타낸다.
`setData()` 메서드는 데이터를 설정하고, `getData()` 메서드는 데이터를 가져온다.
이 두 메서드는 `synchronized` 키워드를 사용하여 동기화되어 있다.

class SharedObject {
    private boolean available = false;
    private int data;

    // 데이터를 설정하고, 사용 가능 상태를 변경하는 메서드
    public synchronized void setData(int data) {
        // 데이터가 이미 사용 가능한 경우, 대기
        while (available) {
            try {
                wait(); // 다른 스레드가 notify()를 호출할 때까지 대기
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 데이터 설정
        this.data = data;
        // 사용 가능 상태 변경
        available = true;
        // 대기 중인 스레드에게 notify
        notify();
    }

    // 데이터를 가져오고, 사용 가능 상태를 변경하는 메서드
    public synchronized int getData() {
        // 데이터가 사용 가능하지 않은 경우, 대기
        while (!available) {
            try {
                wait(); // 다른 스레드가 notify()를 호출할 때까지 대기
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 데이터 반환
        available = false;
        // 대기 중인 스레드에게 notify
        notify();
        return data;
    }
}



`wait()` 및 `notify()` 메서드를 사용하여 프로듀서 스레드가 데이터를 설정할 때,
컨슈머 스레드가 데이터를 가져올 때마다 서로 동기화되고, 데이터의 생성 및 소비가 이루어진다.

public class WaitNotifyExample {
    public static void main(String[] args) {
        SharedObject sharedObject = new SharedObject();

        // Producer 스레드: 데이터를 설정
        Thread producerThread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                sharedObject.setData(i);
                System.out.println("Produced: " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // Consumer 스레드: 데이터를 가져옴
        Thread consumerThread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                int data = sharedObject.getData();
                System.out.println("Consumed: " + data);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        producerThread.start();
        consumerThread.start();
    }
}