Lock 객체 Condition 인터페이스를 통한 대기/알림

키워드 Synchronized와wait()와notify()/notifyAll() 방법을 결합하면 대기 알림을 실현할 수 있고,ReentrantLock은Condition 대상을 빌려 같은 기능을 실현할 수 있으며, 하나의lock 대상은 여러 개의condition 대상을 만들 수 있어 선택적인condition 대상을 선택하여 대기/알림을 할 수 있다.
condition 대상이 알림을 기다리는 간단한 사례를 실현
public class ConditionLockDemo {
	private Lock lock = new ReentrantLock();
	private Condition condition = lock.newCondition();
	public void csleep(){
		try{
			lock.lock();
			System.out.println(Thread.currentThread().getName()+"current time :"+System.currentTimeMillis());
			condition.await();
			System.out.println(Thread.currentThread().getName()+"    current time :"+System.currentTimeMillis());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	public void signal(){
		try{
			lock.lock();
			condition.signal();
		}finally{
			lock.unlock();
		}
	}
}

두 개의 라인을 가동하여 각각 두 가지 방법을 호출하다
public static void main(String[] args) throws InterruptedException {
	final ConditionLockDemo cl = new ConditionLockDemo();
	Thread a = new Thread(new Runnable() {
		@Override
		public void run() {
			cl.csleep();
		}
	}, "A");
	Thread b = new Thread(new Runnable() {
		@Override
		public void run() {
			cl.signal();
		}
	}, "B");
	a.start();
	Thread.sleep(1000);
	b.start();
}

출력:
Acurrent time :1525329885799
A    current time :1525329886799

이 간단한 사례에서
* condition 대상은 lock 대상이 만들고 한 lock 대상은 여러 개의 condition 대상을 만들 수 있습니다
* 알림의 실현을 기다리고 condition 대상의 await() 방법을 빌려 막힌 상태에서 자물쇠를 풀고 signal 방법으로waiting의 라인을 깨운다
* await () 와 signal 방법의 호출은 자물쇠를 얻은 후에 (lock.lock ()
condition 부분 방법 설명
메서드
묘사
await()
현재 스레드가waiting 상태에 들어가고 현재 스레드의 자물쇠를 방출합니다. 현재 스레드는 다른 스레드가signal,signal All,interrupt 방법을 호출할 때까지 깨어납니다. 만약 스레드가await 방법에서 되돌아오면 자물쇠를 가져왔음을 나타냅니다.
awaitUninterruptibly()
위의 방법과 일치하지만, 다른 라인의 중단 방법에 민감하지 않다는 점에서 차이가 있다.
awaitUntil(Date deadline)
현재 스레드는 알림, 중단, 또는 어느 시간대까지 대기 상태로 들어갑니다. 만약 시간대에 도착하지 않으면 알림을 받을 수 있습니다. 방법은true로 되돌아갑니다. 그렇지 않으면 지정된 시간이 되어false로 돌아갑니다.
signal()
자물쇠를 가져오면waiting 상태의 라인을 깨웁니다
signalAll()
자물쇠를 얻은 후 웨이팅 상태의 모든 라인을 깨웁니다
condition 생산자 소비자 모델 실현
세 라인을 번갈아 프린트합니다. 하나, 둘, 셋...
생각:
3개의 스레드, 3개의 condition 대상 만들기
3개의 스레드가 같은 공유 변수의 값을 읽고 값에 따라 막힘 상태에 들어갔는지 판단합니다
, 막힌 상태가 아니면 이 값을 수정하고 다음 라인을 깨우면 A-B-C-A가 번갈아 깨우기
public class ThreeConditionDemo {
	private Lock lock = new ReentrantLock();
	private Condition condition1 = lock.newCondition();
	private Condition condition2 = lock.newCondition();
	private Condition condition3 = lock.newCondition();
	private volatile int count = 1;
	public void printA() {
		try{
			lock.lock();
			while(count!=1){
				condition1.await();
			}
			Thread.sleep(1000);
			System.out.println("1");
			count = 2 ;
			condition2.signal();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	public void printB(){
		try{
			lock.lock();
			while(count!=2){
				condition2.await();
			}
			Thread.sleep(1000);
			System.out.println("2");
			count = 3;
			condition3.signal();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	public void printC(){
		try{
			lock.lock();
			while(count!=3){
				condition3.await();
			}
			Thread.sleep(1000);
			System.out.println("3");
			count = 1;
			condition1.signal();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
}

세 개의 스레드 테스트를 시작합니다.
public static void main(String[] args) {
		final ThreeConditionDemo tcd = new ThreeConditionDemo();
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					tcd.printA();
				}
			}
		});
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					tcd.printB();
				}
			}
		});
		Thread t3 = new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					tcd.printC();
				}
			}
		});
		t1.start();
		t2.start();
		t3.start();
	}

Object 모니터 잠금 및 Condition 메서드 비교
대비항
Object 모니터 방법
Condition
선행 조건
object 객체의 잠금 가져오기
lock을 호출합니다.lock() 잠금 가져오기
호출 방법
object.wait/notify,notifyAll
Condition condition = lock.newCondition()condition.await/signal,signalAll
잠금 해제 대기 상태로 들어가 중단 없음
지원되지 않음
뒷받침
잠금 해제 시간 초과 대기
뒷받침
뒷받침
대기열 수
1개
여러 개,lock은 여러 개의condition을 만들고 하나의condition을 호출할 수 있습니다.await 방법은 대기 대기열에 가입합니다

좋은 웹페이지 즐겨찾기