问一个线程同步的问题

本贴最后更新于 2895 天前,其中的信息可能已经事过境迁

上代码:

import java.util.LinkedList; import java.util.Queue; class BlockingQ { private Object notEmpty = new Object(); private Object notFull = new Object(); private Queue linkedList = new LinkedList(); private int maxLength = 10; public Object take() throws InterruptedException { synchronized (notEmpty) { if (linkedList.size() == 0) { notEmpty.wait(); } synchronized (notFull) { if (linkedList.size() == maxLength) { notFull.notifyAll(); } return linkedList.poll(); } } } public void offer(Object object) throws InterruptedException { synchronized (notEmpty) { if (linkedList.size() == 0) { notEmpty.notifyAll(); } synchronized (notFull) { if (linkedList.size() == maxLength) { notFull.wait(); } linkedList.add(object); } } } }

有点不懂, notFull.wait(); 会释放 notEmpty 吗? 谁能简单的讲讲。


更新:做了个测试,发现确实是会阻塞的,上面的阻塞队列实现有问题:

public class BlockingQTest { public static void main(String [] as) throws InterruptedException { BlockingQ blockingQ = new BlockingQ(); Thread offerThread = new Thread(new OfferTask(blockingQ),"offerThread"); Thread takeThread = new Thread(new TakeTask(blockingQ),"takeThread"); offerThread.start(); takeThread.start(); } } class TakeTask implements Runnable{ private BlockingQ blockingQ; public TakeTask(BlockingQ blockingQ){ this.blockingQ = blockingQ; } @Override public void run() { try { while(true) { Object o = blockingQ.take(); System.out.println("take:" + o); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } } class OfferTask implements Runnable{ private BlockingQ blockingQ; public OfferTask(BlockingQ blockingQ){ this.blockingQ = blockingQ; } @Override public void run() { try { for (int i=0; i < 20; i++){ blockingQ.offer(i); } } catch (InterruptedException e) { e.printStackTrace(); } } }

下面这个实现是没问题的:

import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class BlockingQ { private Lock lock = new ReentrantLock(); private Condition notEmpty = lock.newCondition(); private Condition notFull = lock.newCondition(); private Queue linkedList = new LinkedList(); private int maxLength = 10; public Object take() throws InterruptedException { lock.lock(); try { if (linkedList.size() == 0) { notEmpty.await(); } if (linkedList.size() == maxLength) { notFull.signalAll(); } return linkedList.poll(); } finally { lock.unlock(); } } public void offer(Object object) throws InterruptedException { lock.lock(); try { if (linkedList.size() == 0) { notEmpty.signalAll(); } if (linkedList.size() == maxLength) { notFull.await(); } linkedList.add(object); System.out.println("offer:" + object); } finally { lock.unlock(); } } } 附上代码来源的截图:

a771005f4fcd44908c9c451d76a0ee44.png

80f4a8ced57a417eab05f113976a68c1.png

资料:
http://files.cnblogs.com/files/jobs/Java%E5%B9%B6%E5%8F%91%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E6%95%99%E7%A8%8B.pdf

  • 多线程
    11 引用 • 26 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3194 引用 • 8214 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • qwab16

    不会释放 notEmpty,只会释放自己 notFull 的锁

    1 回复
  • 那这个简单的阻塞队列实现就有问题了啊
    offer 的 notEmpty 如果不会释放
    那 take 如何进入 notEmpty 呢?

    1 回复
  • qwab16

    同步的那段代码块执行完了就会释放,平不影响 take 执行

    2 回复
  • 我做了个测试:

    public class BlockingQTest { public static void main(String [] as) throws InterruptedException { BlockingQ blockingQ = new BlockingQ(); Thread offerThread = new Thread(new OfferTask(blockingQ), "offerThread"); Thread takeThread = new Thread(new TakeTask(blockingQ), "takeThread"); offerThread.start(); takeThread.start(); } } class TakeTask implements Runnable{ private BlockingQ blockingQ; public TakeTask(BlockingQ blockingQ){ this.blockingQ = blockingQ; } @Override public void run() { try { Object o = blockingQ.take(); System.out.println("take:" + o); } catch (InterruptedException e) { e.printStackTrace(); } } } class OfferTask implements Runnable{ private BlockingQ blockingQ; public OfferTask(BlockingQ blockingQ){ this.blockingQ = blockingQ; } @Override public void run() { try { for (int i=0; i < 100; i++){ blockingQ.offer(i); } } catch (InterruptedException e) { e.printStackTrace(); } } }

    00597ee6a45948739ed062cf4883bcfe.png

    确实是不会释放锁的,我写的测试方式有问题吗 ? 死锁了

  • 纠正一下 take 漏了循环 ,只取了一次。。。。。。
    public class BlockingQTest {
    public static void main(String [] as) throws InterruptedException {
    BlockingQ blockingQ = new BlockingQ();
    Thread offerThread = new Thread(new OfferTask(blockingQ),"offerThread");
    Thread takeThread = new Thread(new TakeTask(blockingQ),"takeThread");
    offerThread.start();
    takeThread.start();
    }
    }

    class TakeTask implements Runnable{ private BlockingQ blockingQ; public TakeTask(BlockingQ blockingQ){ this.blockingQ = blockingQ; } @Override public void run() { try { while(true) { Object o = blockingQ.take(); System.out.println("take:" + o); } } catch (InterruptedException e) { e.printStackTrace(); } } } class OfferTask implements Runnable{ private BlockingQ blockingQ; public OfferTask(BlockingQ blockingQ){ this.blockingQ = blockingQ; } @Override public void run() { try { for (int i=0; i < 100; i++){ blockingQ.offer(i); } } catch (InterruptedException e) { e.printStackTrace(); } } }
  • xjtushilei via iPhone

    notEmpty.notifyAll(); 为什么不是 add 结束后。如果不结束,那么上面的 take 被唤醒了,由于 notnull 的🔒的存在并不能取到东西呀

    2 回复
  • 阿里巴巴分享的 pdf 里面就是这样写的

  • 我也不造啊。。。。

请输入回帖内容 ...

推荐标签 标签

  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 2 关注
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖 • 1 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 46 关注
  • Word
    13 引用 • 40 回帖
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    20 引用 • 7 回帖
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    76 引用 • 389 回帖
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 542 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 412 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 567 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    5 引用 • 7 回帖 • 2 关注
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 117 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 639 关注
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    58 引用 • 22 回帖 • 1 关注
  • CodeMirror
    1 引用 • 2 回帖 • 154 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    87 引用 • 139 回帖 • 1 关注
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    267 引用 • 666 回帖 • 1 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    116 引用 • 54 回帖 • 5 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 606 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 75 关注
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    239 引用 • 224 回帖 • 1 关注
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 319 关注
  • Caddy

    Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。

    12 引用 • 54 回帖 • 168 关注
  • 七牛云

    七牛云是国内领先的企业级公有云服务商,致力于打造以数据为核心的场景化 PaaS 服务。围绕富媒体场景,七牛先后推出了对象存储,融合 CDN 加速,数据通用处理,内容反垃圾服务,以及直播云服务等。

    28 引用 • 226 回帖 • 138 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖 • 1 关注
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    171 引用 • 3842 回帖
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 676 关注