问一个线程同步的问题

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

上代码:

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 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖

相关帖子

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • 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

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

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

  • 我也不造啊。。。。

请输入回帖内容 ...

推荐标签 标签

  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖 • 1 关注
  • abitmean

    有点意思就行了

    23 关注
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 10 关注
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 619 关注
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 560 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 597 关注
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 513 关注
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    170 引用 • 414 回帖 • 429 关注
  • 快应用

    快应用 是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。

    15 引用 • 127 回帖 • 3 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    124 引用 • 580 回帖
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    103 引用 • 126 回帖 • 449 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 54 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 352 关注
  • frp

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

    15 引用 • 7 回帖 • 9 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    247 引用 • 1347 回帖
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    51 引用 • 37 回帖
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    17 引用 • 236 回帖 • 418 关注
  • danl
    64 关注
  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    90 引用 • 383 回帖 • 1 关注
  • WebClipper

    Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。

    3 引用 • 9 回帖 • 5 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    82 引用 • 122 回帖 • 620 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    40 引用 • 40 回帖 • 2 关注
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 2 关注
  • 七牛云

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

    25 引用 • 217 回帖 • 166 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 181 关注
  • SQLite

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

    4 引用 • 7 回帖 • 2 关注