Synchronization Control - #5

김병우·2024년 3월 12일
0

Java-Thread

목록 보기
5/5

실습 자료 : https://github.com/helloJosh/nhn-homework-thread-study

1. Synchronization Control

자바에서는 synchronized method, block을 제어하기 위해 wait(), notify(), notifyAll()을 지원한다. 네트워크 프로그래밍이 이런 식으로 프로그래밍되어있어 은근 중요한 부분 같다.

  • Wait() : syncrhonized 영역에서 lock을 소유한 thread가 어떠한 이유에서 자신의 제어권을 양보하고 WAITING 또는 TIMED_WAITING 상태에서 대기하기 위해서 사용된다.
  • notify()와 notifyAll() : syncrhonized 영역에서 WAITING 상태에 있는 다른 thread를 다시 RUNNABLE 상태로 변경시키는 역할을 한다.

    wait, notify, notifyAll은 Thread의 static method가 아닌 instance method이다.

코드로 알아보자

public class Data {
    private String packet;
    private boolean transfer = true;

    public synchronized String receive(){
        while(transfer){
            try{
                wait();
                //Thread.sleep(1000); 계속 리시버만 돌고 있다.
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
            }
        }
        transfer = true;

        String returnPacket = packet;
        notifyAll();
        return returnPacket;
    }
    public synchronized void send(String packet){
        while(!transfer){
            try{
                wait();
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
            }
        }
        transfer = false;
        this.packet = packet;
        notifyAll();
    }
    public static void main(String[] args) {
        Data data = new Data();

        Thread sender = new Thread(new Sender(data));
        Thread receiver1 = new Thread(new Receiver(data));
        Thread receiver2 = new Thread(new Receiver(data));

        sender.start();
        receiver1.start();
        receiver2.start();
    }
}
public class Receiver implements Runnable{
    private Data load;
    public Receiver(Data load) {
        this.load = load;
    }
    public void run(){
        for(String receivedMessage = load.receive(); !"End".equals(receivedMessage);receivedMessage= load.receive()){
            System.out.println(receivedMessage);
            try{
                Thread.sleep(ThreadLocalRandom.current().nextInt(1000,5000));
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                System.err.println("Thread Interrupted");
            }
        }
    }
}
public class Sender implements Runnable {
    private Data data;
    public Sender(Data data) {
        this.data = data;
    }
    public void run(){
        String packets[] ={
            "1st packet",
            "2nd packet",
            "3rd packet",
            "4th packet",
            "End"
        };

        for(String packet : packets){
            data.send(packet);
            try{
            	Thread.sleep(ThreadLocalRandom.current().nextInt(1000,5000));
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                System.err.println("Thread Interrupted");
            }
        }
    }
}
  • 위 와 같이 Data Class에서 method에서 wait()을 호출해서 다른 thread가 일이 끝날 때까지 기다린다.
  • 일이 끝난 쓰레드는 notifyAll()을 호출하여 일이 끝났다는 것을 다른 쓰레드에게 알려준다.

참고

  • 위에 주석에 있는 것처럼 wait() 과 sleep()은 다르다.
  • wait()은 공유 자원에 접근 안한 상태로 대기중인 것이고
  • sleep()은 자원을 갖고 있는 상태에서 쉬는 것이다.
  • 따라서 wait()을 주석하고 sleep()를 주석을 풀게되면 Receiver만 돌게 된다.
profile
백엔드개발자

0개의 댓글