zoukankan      html  css  js  c++  java
  • 【Java多线程通信】syncrhoized下wait()/notify()与ReentrantLock下condition的用法比较

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6556925.html 

        一:syncrhoized使用同一把锁的多个线程用通信实现执行顺序的调度

            我们知道,使用syncrhoized关键字修饰一个代码块、一个方式时,在代码块、方法执行完毕之前是不会释放掉所持有的锁的,在执行期间,其他申请这个锁的线程只能阻塞等待。这些等待的线程被安排在一个等待队列中。

            现在,由于某种原因,在当前同步代码块A中需要另一个同步代码块B先执行完,然后A才能继续进行下去。而同步代码块B是另一个线程来执行的,并且申请的是同一个同步锁。此时,就需要在A中把锁让出去并且让A线程挂起(即让出CPU,进入等待队列)【通过wait()方法挂起线程,进入该同步锁的等待队列】。B在获得同步锁并且执行完后,则通过 notify()/notifyAll() 方法唤醒该同步锁的等待队列中的线程。A被唤醒后就由等待队列中弹出,进入就绪态,等待获取CPU使用权继续执行。

        二:ReentrantLock加锁的线程之间的通信实现执行调度

        ReentrantLock加锁的线程是通过Condition对象的await()、signal()/signalAll()方法来挂起当前线程(挂起前先调用lock.unlock()释放掉锁),唤醒相应线程(在某condition条件下等待的线程)先执行来实现的。

        Condition的最大改进在于:更加精确地进行调度。当前线程可以显式定义在某处“因何情况而等待”,也可以在释放锁后某处显式地通知“因何情况而等待的线程可以启动继续执行了”。而不再是笼统地申请同一把锁的等待线程全部启动。

        我们来看一下官方提供的例子:

    package locks;
    import java.util.Random;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class AppOfficial {
    
        /**
         * BoundedBuffer 是一个定长100的集合,当集合中没有元素,take方法需要等待,直到有元素时才返回元素
         * 当集合满了,要等待直到元素被take之后才执行put的操作
         */
        static class BoundedBuffer {
         //定义一个锁对象
            final Lock lock = new ReentrantLock();
         //定义两种被唤醒的条件:非满、非空
            final Condition notFull = lock.newCondition();
            final Condition notEmpty = lock.newCondition();
    
            final Object[] items = new Object[100];
            int putptr, takeptr, count;
    
            public void put(Object x) throws InterruptedException {
                System .out.println("put wait lock");
            //加锁进行put操作
                lock.lock();
                System.out.println("put get lock");
                try {
                  //当集合满了,则等待 非满 情况的发生
                    while (count == items.length) {
                        System.out.println("buffer full, please wait");   

    //在 非满 条件下挂起,等待非满条件的唤醒操作才继续执行下去 notFull.await(); } items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; //执行完插入操作后,集合非空,通知 非空 条件下挂起的线程 可以继续进行take操作了 notEmpty.signal(); } finally { lock.unlock(); } } public Object take() throws InterruptedException { System.out.println("take wait lock"); lock.lock(); System.out.println("take get lock"); try { while (count == 0) { System.out.println("no elements, please wait");
    //在 非空 条件下挂起 notEmpty.await(); } Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0; --count; //集合不是满的了,唤醒在 非满 情况下挂起的put线程可以继续执行put操作 notFull.signal(); return x; } finally { lock.unlock(); } } } public static void main(String[] args) { final BoundedBuffer boundedBuffer = new BoundedBuffer(); Thread t1 = new Thread(new Runnable() { @Override public void run() { System.out.println("t1 run"); for (int i=0;i<1000;i++) { try { System.out.println("putting.."); boundedBuffer.put(Integer.valueOf(i)); } catch (InterruptedException e) { e.printStackTrace(); } } } }) ; Thread t2 = new Thread(new Runnable() { @Override public void run() { for (int i=0;i<1000;i++) { try { Object val = boundedBuffer.take(); System.out.println(val); } catch (InterruptedException e) { e.printStackTrace(); } } } }) ; t1.start(); t2.start(); } }
  • 相关阅读:
    php CURL 发送请求封装
    PHP AES加解密(兼容php5,php7)
    vscode jshint 报'import' is only available in ES6 (use 'esversion: 6'). (W119)错误
    vue-cli4 + TS构建新项目
    搭建vue项目
    分享一个自然语言汉语时间语义识别的工具类
    图像检索阶段性总结
    mysql常用操作
    javascript在页面head内动态插入style
    iScroll-5拉动刷新功能实现与iScroll-4上拉刷新的一点改进
  • 原文地址:https://www.cnblogs.com/ygj0930/p/6556925.html
Copyright © 2011-2022 走看看