Lock的Condition使用

            Lock是java 1.5中引入的线程同步工具,它主要用于多线程下共享资源的控制。

Condition 本质是一个接口,它包含如下方法

// 让线程进入等通知待状态 
void await() throws InterruptedException; 
void awaitUninterruptibly();
//让线程进入等待通知状态,超时结束等待状态,并抛出异常  
long awaitNanos(long nanosTimeout) throws InterruptedException; 
boolean await(long time, TimeUnit unit) throws InterruptedException; 
boolean awaitUntil(Date deadline) throws InterruptedException; 

//将条件队列中的一个线程,从等待通知状态转换为等待锁状态 
void signal(); 

//将条件队列中的所有线程,从等待通知阻塞状态转换为等待锁阻塞状态
void signalAll();

           一个Condition实例的内部实际上维护了一个队列,队列中的节点表示由于(某些条件不满足而)线程自身调用await方法阻塞的线程。Condition接口中有两个重要的方法,即 await方法和 signal方法。线程调用这个方法之前该线程必须已经获取了Condition实例所依附的锁。这样的原因有两个,(1)对于await方法,它内部会执行释放锁的操作,所以使用前必须获取锁。(2)对于signal方法,是为了避免多个线程同时调用同一个Condition实例的singal方法时引起的(队列)出列竞争。下面是这两个方法的执行流程。

          await方法:

                            1. 入列到条件队列(注意这里不是等待锁的队列

                            2. 释放锁

                            3. 阻塞自身线程

                             ------------被唤醒后执行-------------

                            4. 尝试去获取锁(执行到这里时线程已不在条件队列中,而是位于等待(锁的)队列中,参见signal方法)

                                4.1 成功,从await方法中返回,执行线程后面的代码

                                4.2 失败,阻塞自己(等待前一个节点释放锁时将它唤醒)

         注意:await方法时自身线程调用的,线程在await方法中阻塞,并没有从await方法中返回,当唤醒后继续执行await方法中后面的代码(也就是获取锁的代码)。可以看出await方法释放了锁,又尝试获得锁。当获取锁不成功的时候当前线程仍然会阻塞到await方法中,等待前一个节点释放锁后再将其唤醒。


         signal方法:

                           1. 将条件队列的队首节点取出,放入等待锁队列的队尾

                           2. 唤醒该节点对应的线程

         注意:signal是由其它线程调用


Lock和Condition的使用例程

public class ConditionCommunication {
/**
* @param args
*/
public static void main(String[] args) {

final Business business = new Business();
new Thread(new Runnable() {
        @Override
      public void run() {
          for(int i=1;i<=50;i++){
              business.sub(i);
                 }
             }}).start();
             for(int i=1;i<=50;i++){
              business.main(i);
                 }
     }


         static class Business {
              Lock lock = new ReentrantLock();
              Condition condition = lock.newCondition();
              private boolean bShouldSub = true;
             public  void sub(int i){
                          lock.lock();
                     try{
                       while(!bShouldSub){
                   try {
                     condition.await();
                        } catch (Exception e) {
                    e.printStackTrace();
                    }
            }
                 for(int j=1;j<=10;j++){
                    System.out.println("sub thread sequence of " + j + ",loop of " + i);
         }
             bShouldSub = false;
            condition.signal();
            }finally{
              lock.unlock();
        }
    }
 
           public  void main(int i){
                  lock.lock();
                   try{
                       while(bShouldSub){
try {
                                    condition.await();
                                       } catch (Exception e) {
                                                 e.printStackTrace();
                                                                           }
  }
                                      for(int j=1;j<=100;j++){
                                   System.out.println("main thread sequence of " + j + ",loop of " + i);
                                        }
                             bShouldSub = true;
                              condition.signal();
                       }finally{
                             lock.unlock();
                            }
               }

        }
}

Lock与synchronized的区别

          1. Lock的加锁和解锁都是由java代码配合native方法(调用操作系统的相关方法)实现的,而synchronize的加锁和解锁的过程是由JVM管理的

          2. 当一个线程使用synchronize获取锁时,若锁被其他线程占用着,那么当前只能被阻塞,直到成功获取锁。而Lock则提供超时锁和可中断等更加灵活的方式,在未能获取锁的     条件下提供一种退出的机制。

          3. 一个锁内部可以有多个Condition实例,即有多路条件队列,而synchronize只有一路条件队列;同样Condition也提供灵活的阻塞方式,在未获得通知之前可以通过中断线程以    及设置等待时限等方式退出条件队列。

         4. synchronize对线程的同步仅提供独占模式,而Lock即可以提供独占模式,也可以提供共享模式


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值