输出:

WorkerTwo:setp into critical section
WorkerTwo:call sayHello()
WorkerOne:step into critical section
  2、条件对象Condition,相当于wait-notify机制,提供一种线程间的等待通知机制,condition中的等待-通知方法是await(),signal(),signalAll(),也需要在互斥环境下被调用。

(1) 相关的接口

创建Condition对象,Condition对象是跟Lock关联在一起的。

Lock locker = new ReentrantLock();
Condition cond = locker.newCondition();
把此线程放到条件的等待集中。

void await();
解除此条件的等待集中所有线程的阻塞状态。

void signalAll();
在此条件的等待集中随机选择一个线程,解除其阻塞状态。

void signal();

(2) 使用的基本结构:

//初始时ok_to_proceed为false.
locker.lock()
try{
     while(!ok_to_proceed){
//进入等待此条件集中,被阻塞,它维持状态直到另一个线程调用同一个条件上的。
//signalAll/signal方法时为止。
       cond.await();
     }
}finally{
cker.unlock();
}

locker.lock();
   try{
      //调用将解除所有等待此条件下的线程的阻塞状态。当线程从等待集中被移走时,它们将再次成为可运行的,调度器将再次激活它们    
      //此时,它们将试图重新进入对象。一旦锁可获得,它们中的某个线程将从await调用返回,从而获得锁并从它被阻塞的地方继续执行。
      ok_to_proceed = true;
      cond.signalAll() or cond.signal();
   }finally{
       locker.unlock();
   }
ok_to_proceed也是为了防止wait-notify出现的问题,即再wait之间,notify()已经给出通知,此时wait只会一直等待下去,这样保证了signal()线程的通知被await()线程接收到。

(3) 测试代码:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class GlobalV{
    public final static Lock locker = new ReentrantLock();
    public final static Condition cond = locker.newCondition();
    public static boolean to_proceed = false;
}
 
class Response extends Thread{
    public void run(){
        while(true){
            GlobalV.locker.lock();
            try{
                while(!GlobalV.to_proceed){
                    GlobalV.cond.await();
                }
System.out.println("Response:finish a job");
                GlobalV.to_proceed = false;
                
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                GlobalV.locker.unlock();
            }   
        }
    }
}
 
class Request extends Thread{
    public void run(){
        while(true){
            GlobalV.locker.lock();  
            try{
                GlobalV.to_proceed = true;
                GlobalV.cond.signalAll();
                System.out.println("Request:send a job to Response");   
            }finally{
                GlobalV.locker.unlock();
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
 
public class Test6 {
    public static void main(String[] args) {
        Request req = new Request();
        Response res = new Response();
        req.start();
        res.start();
    }
}