问一个线程同步的问题

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

上代码:

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

    3169 引用 • 8207 回帖

相关帖子

欢迎来到这里!

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

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

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

    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

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

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

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

  • 查看全部回帖

推荐标签 标签

  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 1 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 135 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    186 引用 • 318 回帖 • 340 关注
  • 智能合约

    智能合约(Smart contract)是一种旨在以信息化方式传播、验证或执行合同的计算机协议。智能合约允许在没有第三方的情况下进行可信交易,这些交易可追踪且不可逆转。智能合约概念于 1994 年由 Nick Szabo 首次提出。

    1 引用 • 11 回帖 • 10 关注
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 23 关注
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 366 关注
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖 • 205 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    207 引用 • 2031 回帖
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    4 引用 • 16 回帖 • 1 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 413 关注
  • 996
    13 引用 • 200 回帖
  • wolai

    我来 wolai:不仅仅是未来的云端笔记!

    2 引用 • 14 回帖 • 4 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 609 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    675 引用 • 535 回帖
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 180 关注
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    198 引用 • 120 回帖
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖
  • Typecho

    Typecho 是一款博客程序,它在 GPLv2 许可证下发行,基于 PHP 构建,可以运行在各种平台上,支持多种数据库(MySQL、PostgreSQL、SQLite)。

    12 引用 • 60 回帖 • 466 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖 • 2 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖
  • 工具

    子曰:“工欲善其事,必先利其器。”

    276 引用 • 686 回帖
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖 • 1 关注
  • Java

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

    3169 引用 • 8207 回帖
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    333 引用 • 323 回帖 • 56 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 2 关注
  • 分享

    有什么新发现就分享给大家吧!

    242 引用 • 1746 回帖
  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 242 关注