자바 멀티스레드 동기화(wait, notify, synchronized)이론.실습(자바/JAVA/자바강좌/자바동영상/자바강의/JAVA강의/JAVA동영상/JAVA교육/자바교육/자바학원)
1. 스레드 동기화 방법
wait
Object 클래스의 메소드로 이 메소드를 호출하는 스레드는 그 실행이 멈추게 된다. 하지만 아무 스레드나 실행이 멈추는 것은 아니며 호출하는 객체의 모니터를 가지고 있는 경우에만(synchronized 구문 안에 들어와 있는 경우) 해당이 된다. 즉 객체의 모니터를 가지고 있는 스레드가 wait 메소드를 호출하면 실행이 멈춘다는 뜻이다. 멈춘스레드는 그 객체의 모니터를 반환하고 대기한다.
이렇게 멈춘 스레드를 깨우려면 notify() 메소드를 호출하든지 wait() 메소드에 기다릴 시간에 대한 인자를 주어야 한다. 물론 notify로 깨우려면 객체에 대한 모니터가 필요하다.(synchronized 구문 안에 들어와 있는 경우)
notify를 호출한 스레드가 모니터를 반환 할 때까지 (synchronized를 벗어날때 까지) 실제 깨어 있는 것이 아니다. notify를 호출한 스레드가 모니터를 반환하면 그제서야 wait되었던 스레드가 깨어난다.
notify
대기하는 스레드가 여럿 인경우 notify를 하면 어느 스레드가 깨어날지는 모른다. 그저 하나가 선택될 뿐이다. 이경우 전부 깨우기 위해서는 notifyAll 을 이용한다.
이 객체에 wait()하고 있는 쓰레드 중 한 쓰레드를 선택하여 재시작 한다.
다시 Monitor(lock)을 획득하지 못하면 기다린다
notifyAll
이 객체에 wait()하고 있는 모든 스레드 재시작
이 중 한 개만이 Monitor(lock)을 획득하고 재시작
wait(long timeout)
Timeout까지 대기한다.즉 시간이 자나면 notify() 효과를 갖는다
주의점
condition을 검사하는 loop를 만들어야
synchronized void someMethod() {
...
while( !condition ) {
wait()
wait와 notify의 용도
한 스레드가 어떤 객체의 메소드를 호출 할때 어떤 조건을 만족해야 한다면 이 스레드는 자신이 아직 이 메소드를 실행 할 준비가 되지 않았으므로 스스로 조건이 될 때까지 기다려야 한다. 이때 객체의 모니터를 얻고 wait를 호출함으로서 조건을 기다리게 된다. 이때 다른 스레드가 조건이 만족되었음을 알고 notify를 호출하여 스레드는 깨어나서 만족된 조건하에서 남은 작업을 진행하게 되는 것이다.
2. 실습
package javatest;
class SharedData {
private boolean isFullData = false;
private int data;
// 어느 한순간에는 하나의 스레드만 put
// 데이터가 차있으면 wait한다.
public synchronized void put(int data) {
try {
while(isFullData) // 데이터가 있으면 대기
wait();
} catch(InterruptedException e ) {}
this.data = data; //데이터가 없으면 데이터를 채움
isFullData = true; //데이터 차있다고 표시
notifyAll(); // 대기하는 모든 스레드 깨움
}
// 어느 한순간에는 하나의 스레드만 get
// 데이터가 없으면 wait 한다.
public synchronized int get() {
try {
while( !isFullData) // 데이터가 없으면 대기
wait();
} catch(InterruptedException e ) {}
isFullData = false; //데이터 없다고 표시
notifyAll(); // 대기하는 모든 스레드 깨움
return data; // 데이터를 꺼냄
}
}
class Writer extends Thread {
private SharedData shared;
private int data;
public Writer(String name, SharedData shared, int data) {
super.setName(name);
this.shared = shared;
this.data = data;
}
public void run() {
shared.put(data); //System.out.println( getName() + " put " + data);
shared.put(data+1); //System.out.println( getName() + " put " + (data+1));
}
}
class Reader extends Thread {
SharedData shared;
public Reader(String name, SharedData shared) {
super.setName(name);
this.shared = shared;
}
public void run() {
while(true)
System.out.println( getName() + " got " + shared.get() );
}
}
class WaitTest
{
public static void main(String[] args)
{
SharedData shared = new SharedData();
Reader r1 = new Reader("READER-1", shared);
Reader r2 = new Reader("READER-2", shared);
Writer w1 = new Writer("WRITER-1", shared, 10);
Writer w2 = new Writer("WRITER-2", shared, 20);
r1.start();
r2.start();
w1.start();
w2.start();
}
}
#자바스레드, #자바쓰레드, #자바Thread, #자바volatile, #자바Atomic, #자바wait, #자바notify, #자바synchronized, #스레드동기화, #스레드, #volatile, #자바, #JAVA, #자바동영상, #자바강의, #자바교육, #자바강좌, #자바동영상강의, #추천자바강의, #추천자바강좌, #JAVA동영상, #JAVA강의, #JAVA강좌, #JAVA교육, #JAVA, #추천JAVA강의, #추천JAVA교육, #추천JAVA강좌, #자바소스, #자바온라인교육, #자바온라인강의
댓글 없음:
댓글 쓰기