文档章节

Lock && Condition_实现有界缓存

秋风醉了
 秋风醉了
发布于 2014/09/02 19:48
字数 761
阅读 168
收藏 0

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

Lock && Condition_实现有界缓存

Lock是一种广义的内置锁,Condition也是一种广义的内置条件队列

内置条件队列存在一些缺陷。每个内置锁都只能有一个相关的条件队列,因而多个线程可能在同一个条件队列上等待不同的条件谓词,并且在最常见的加锁模式下公开条件队列对象。

这些因素都使得无法满足在使用notifyAll时所有等待线程为同一类型的需求。如果想编写一个带有多个条件谓词的并发对象,或者想获得除了条件队列可见性的更多控制权,就可以使用显示的Lock和Condition而不是内置锁和内置条件队列,这是一种更灵活的选择。

Lock比内置锁提供了更为丰富的功能,Condition同样比内置条件队列提供了更丰富的功能:在每个锁上可能存在多个等待、条件等待可以是可中断的、基于时限的等待,以及公平的或非公平的队列操作。

与内置条件队列不同的是,对于每个Lock,可以有任意数量的Condition对象。Condition对象继承了相关的Lock对象的公平性,对于公平的锁,线程会依照FIFO顺序从Condition.await中释放。

下面这段程序给出了有界缓存的另一种实现,即‍使用两个Condition,分别为notFull和notEmpty‍,用于表示”非满“和”非空“两个条件谓词。当缓存为空时,take将阻塞并等待notEmpty,此时put向notEmpty发送信号,可以解除任何在take中阻塞的线程。

 

使用显示条件变量的有界缓存

package sync;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created with IntelliJ IDEA.
 * User: ASUS
 * Date: 14-9-1
 * Time: 下午9:20
 * To change this template use File | Settings | File Templates.
 */
public class ConditionBoundedBuffer<T> {

    protected final Lock lock = new ReentrantLock();

    //条件谓词:notFull
    private final Condition notFull = lock.newCondition();
    //条件谓词:notEmpty
    private final Condition notEmpty = lock.newCondition();
    private final T[] items;
    private int tail, head, count;

    protected ConditionBoundedBuffer(int size) {
        items = (T[]) new Object[size];
    }

    /**
     * 阻塞并直到notFull
     *
     * @param x
     * @throws InterruptedException
     */
    public void put(T x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length) {
                // 阻塞,等待非满条件
                System.out.println("not full await");
                notFull.await();
            }

            items[tail] = x;
            if (++tail == items.length) {
                tail = 0;
            }

            ++count;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }


    /**
     * 阻塞并直到notEmpty
     *
     * @return
     * @throws InterruptedException
     */
    public T take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                // 阻塞,等待非空条件
                System.out.println("not empty await");
                notEmpty.await(); //现在有界缓存为空,要等到非空状态才能取出元素
            }

            T x = items[head];
            items[head] = null;
            if (++head == items.length) {
                head = 0;
            }
            --count;
            notFull.signal(); //元素已被取出,通知非满状态
            return x;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String args[]) {

        final ConditionBoundedBuffer buffer = new ConditionBoundedBuffer(10);

        //线程t2打印缓存中的消息
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        System.out.println(buffer.take());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        //线程t1放入缓存消息
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    try {
                        buffer.put(new String("sadsasd"));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        t2.start();
        t1.start();
    }
}

============END============

© 著作权归作者所有

秋风醉了
粉丝 253
博文 532
码字总数 405755
作品 0
朝阳
程序员
私信 提问
java并发编程之wait¬ify VS lock&condition

jdk5之前线程同步可以用synchronized/wait/notify来进行控制,jdk5以后新添加了lock/condition。他们之间有什么联系与区别的?本文就用一个例子循序渐进的给大家展示一下: 首先来看一个有界...

若鱼1919
2018/07/06
0
0
Java并发系列9--阻塞队列BlockingQueue

今天要讲的可谓是大名鼎鼎,在并发编程中比较常见的一个类。 顾名思义是表示一个阻塞队列,注意这两个词:阻塞和队列。可以拿我们熟悉的生产者-消费者队列来举例,一条流水线上,A生产零件,...

大大枣
2018/07/04
45
0
读书笔记之《Java并发编程的艺术》-java中的锁

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
428
0
Condition-线程通信更高效的方式

使用Lock如何处理线程通信。 引入本篇的主角--Condition,Condition将 Object监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意Lock实现组合使用,为...

loubobooo
03/07
8
0
Java 并发编程(一)

Java 并发编程(一) 同步容器 1.Vector,Hashtable。实现线程安全的方式是:将它们的状态封装起来,并对每个共有方法进行同步,使得每次只有一个线程能访问容器的状态。使用了Java监视器模式...

战地春梦
2016/08/18
36
0

没有更多内容

加载失败,请刷新页面

加载更多

ArrayList 源码分析

一、概述 本文基于 JDK8 ArrayList 底层通过动态数组的数据结构实现 内存需要连续的空间保证 添加操作涉及到数组的动态扩容 添加,删除都涉及到位置移动操作 随机查找效率快(下标查找) Ar...

hncboy
今天
4
0
采购单品汇总_华南.xlsx

import pandas as pdimport matplotlib.pyplot as pltimport matplotlib as mp1mp1.rcParams["font.family"] = "STFangsong"# 加载《销售》表数据df1 = pd.read_excel(r"C:\Us......

龙玉滕
今天
5
0
OSChina 周五乱弹 —— 一次四千 要4次还能多给一千

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @这次装个文艺青年吧 :#今日歌曲推荐# 分享金志文的单曲《远走高飞》: 版权又回来了现在听歌得好几个软件 《远走高飞》- 金志文 手机党少年们...

小小编辑
今天
11
0
Spring Cloud Alibaba 实战(十) - Spring Cloud GateWay

> 本文主要内容是:为什么要使用网关,整合Gateway,Gateway核心学习:Route,Predicate,Filter,最后使用Gateway聚合微服务请求 先总结至此的架构 1 网关的价值 不使用网关行嘛? 各个请求直接打在...

JavaEdge
今天
4
0
【CKB.DEV 茶话会】第二期:聊聊 CKB 钱包和 Nervos DAO 全流程

CKB.DEV 茶话会第二期:聊聊 CKB 钱包和 Nervos DAO 全流程 为了鼓励更多优秀的开发者和研究人员参与到 CKB 的开发和生态建设中去,我们希望组织一系列 CKB Developer Seminar(CKB.DEV 茶话...

NervosCommunity
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部