zoukankan      html  css  js  c++  java
  • 通过Lock对象以及Condition对象实现多线程同步

    通过Lock对象以及Condition对象实现多线程同步

    在之前的学习中,无论是通过synchronized建立同步代码块,还是通过synchronized建立同步函数,都是把对象看成一把锁来实现同步,这种解释有点牵强,而且在消费者—生产者的那个实例中,其实还有个问题,那就是在避免线程全部冻结时,没必要把相同功能的线程解冻,只要把其他功能的线程解冻即可,也就是说消费者线程只要解冻生产者线程即可,没必要把其他消费者线程也解冻,为了解决这些问题,java1.5版本推出了同步的升级办法,那就是通过Lock对象和Condition对象实现同步。

    新的同步办法不再需要synchronized关键字,而引入了更加形象的Lock。

    Lock实质上是是一个接口,在创建对象时,使用Lock的子类ReentrantLock来建立对象。

    使用方法:建立对象后,在需要同步的代码前一行写    Lock对象.lock();   ,在同步代码后一行写   Lock对象.unlock();

    Lock对象用来控制线程的进出,而对线程的操作则由Condition对象来操作;

    对应关系:

    wait——await(两者均抛出异常)

    notify——signal

    notifyAll——signalAll

    Condition同样是接口,建立方法(比较神奇)       Condition 对象名=Lock对象.newCondition();

    例如:1-9 个数,A线程执行123.然后由B线程接着执行456.最后在由A线程执行789

    代码:

    package com.huojg.test;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /*
     * 
     * 1-9 个数,A线程执行123.然后由B线程接着执行456.最后在由A线程执行789
     * 
     * 
     * **/
    public class lock {
        static class NumberWrapper {
            public int value = 1;
        }
        
    public static void main(String[] args) {
        
        //初始化可重入锁
        final Lock lock=new ReentrantLock();
        //第一个条件当屏幕上输出到3
        final Condition reachThreeCondition=lock.newCondition();
        //第一个条件当屏幕上输出到6
        final Condition reachSixCondition=lock.newCondition();     
        //NumberWrapper只是为了封装一个数字,一边可以将数字对象共享,并可以设置为final
                //注意这里不要用Integer, Integer 是不可变对象
                final NumberWrapper num = new NumberWrapper();
        //初始化A线程
        Thread threadA=new Thread( new Runnable() {
            public void run() {
                //需要先获得锁
                lock.lock();
                try {
                    System.out.println("threadA start write");
                    while (num.value<=3) {
                        System.out.println(num.value);
                        num.value++;                    
                    }
                    //输出到3时要signal,告诉B线程可以开始了
                    reachThreeCondition.signal();
                } finally{
                    lock.unlock();
                }
                
                lock.lock();
                try {
                    //等待输出6的条件
                    reachSixCondition.await();
                    System.out.println("threadA start write");
                    //输出剩余数字
                    while (num.value <= 9) {
                        System.out.println(num.value);
                        num.value++;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }                
            }
        });
        
        Thread threadB =new Thread(new  Runnable() {
            public void run() {
            try {
                lock.lock();
                while (num.value<=3) {
                    //等待3输出完毕的信号
                    reachThreeCondition.await();
                }
                
            }catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
                
                
            try {
                lock.lock();
                //已经收到信号,开始输出4,5,6
                System.out.println("threadB start write");
                while (num.value <= 6) {
                    System.out.println(num.value);
                    num.value++;
                }
                //4,5,6输出完毕,告诉A线程6输出完了
                reachSixCondition.signal();
                
            } finally{
                lock.unlock();
            }
                
            }
        });
    
        //启动两个线程
                threadB.start();
                threadA.start();    
    
    }
    
    }

    结果:

    threadA start write
    1
    2
    3
    threadB start write
    4
    5
    6
    threadA start write
    7
    8
    9
    

      

    Condition对象的优势在于,signal只能唤醒被相同Condition对象的await方法冻结的线程,因此,可以建立多个Condition对象,分别用来冻结和解冻不同功能的线程

    最后要注意的是,Lock接口属于类包Java.util.concurrent.locks

  • 相关阅读:
    八进制转换成十进制(你会明白的,呵呵)
    从键盘读取7个数(150)的整数值,每读一个值打印出该值个数的*号.
    两个字符串的连接程序
    判断一个素数能被几个9整除.
    809*??=800*??+9*??+1 其中??代表的两位数,8*??的结果为两位数,9*??的结果为3位数。求??代表的两位数,及809*??后的结果。
    一个偶数总能表示为两个素数的和.
    07所能组成的奇数的个数
    asp.net .ashx文件使用Server.MapPath解决方法
    MVC常见问题小总结
    amcharts_2.6.13左上角的广告咱去掉
  • 原文地址:https://www.cnblogs.com/huojg-21442/p/7118163.html
Copyright © 2011-2022 走看看