Java中的BlockingQueue是完全线程安全的吗

2024-04-02

我知道文档说该对象是线程安全的,但这是否意味着从所有方法对它的所有访问都是线程安全的?所以如果我打电话put()同时从多个线程上进行操作take()在同一时刻,不会有什么不好的事情发生吗?

我问这个问题是因为这个答案让我再次猜测:https://stackoverflow.com/a/22006181/4164238 https://stackoverflow.com/a/22006181/4164238


快速回答是肯定的,它们是线程安全的。但我们不要把它留在那里......

首先是一点家务管理,BlockingQueue是一个接口,任何非线程安全的实现都将违反记录的契约。您包含的链接指的是LinkedBlockingQueue,这有一些聪明之处。

The 您添加的链接 https://stackoverflow.com/questions/2695426/are-linkedblockingqueues-insert-and-remove-methods-thread-safe/22006181#22006181做了一个有趣的观察,是的,里面有两把锁LinkedBlockingQueue。然而,它无法理解“简单”实现可能遇到的边缘情况实际上正在被处理,这就是为什么 take 和 put 方法比人们最初预期的更复杂的原因。

LinkedBlockingQueue进行了优化以避免在读取和写入时使用相同的锁,这减少了争用,但是为了正确的行为,它依赖于队列不为空。当队列中有元素时,推入点和弹出点不在同一内存区域,可以避免争用。然而,当队列为空时,争用就无法避免,因此需要额外的代码来处理这种常见的“边缘”情况。这是代码复杂性和性能/可扩展性之间的常见权衡。

那么问题来了,如何LinkedBlockingQueue知道队列何时为空/非空,从而处理线程?答案是它使用一个AtomicInteger and a Condition作为两个额外的并发数据结构。这AtomicInteger用于检查队列的长度是否为零,条件用于等待信号以在队列可能处于所需状态时通知等待线程。这种额外的协调确实会产生开销,但在测量中表明,当增加并发线程的数量时,该技术的开销低于使用单个锁引入的争用。

下面我复制了代码LinkedBlockingQueue并添加了解释它们如何工作的评论。在高水平上,take()首先锁定所有其他调用take()然后发出信号put()有必要的。put()以类似的方式工作,首先它会阻止所有其他调用put()然后发出信号take()如果需要的话。

来自put() method:

    // putLock coordinates the calls to put() only; further coordination
    // between put() and take() follows below
    putLock.lockInterruptibly();
    try {
        // block while the queue is full; count is shared between put() and take()
        // and is safely visible between cores but prone to change between calls
        // a while loop is used because state can change between signals, which is
        // why signals get rechecked and resent.. read on to see more of that 
        while (count.get() == capacity) { 
                notFull.await();
        }

        // we know that the queue is not full so add
        enqueue(e);
        c = count.getAndIncrement();

        // if the queue is not full, send a signal to wake up 
        // any thread that is possibly waiting for the queue to be a little
        // emptier -- note that this is logically part of 'take()' but it
        // has to be here because take() blocks itself
        if (c + 1 < capacity)
            notFull.signal();
    } finally {
        putLock.unlock();
    }
    if (c == 0)
        signalNotEmpty();

From take()

    takeLock.lockInterruptibly();
    try {
            // wait for the queue to stop being empty
            while (count.get() == 0) {
                notEmpty.await();
            }

        // remove element
        x = dequeue();

        // decrement shared count
        c = count.getAndDecrement();

        // send signal that the queue is not empty
        // note that this is logically part of put(), but
        // for thread coordination reasons is here
        if (c > 1)
            notEmpty.signal();
    } finally {
        takeLock.unlock();
    }
    if (c == capacity)
        signalNotFull();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java中的BlockingQueue是完全线程安全的吗 的相关文章

  • java.lang.NoClassDefFoundError:org.apache.batik.dom.svg.SVGDOMImplementation

    我在链接到我的 Android LibGDX 项目的 Apache Batik 库时遇到了奇怪的问题 但让我们从头开始 在 IntelliJ Idea 中我有一个项目 其中包含三个模块 Main Android 和 Desktop 我强调的
  • Grails 3.x bootRun 失败

    我正在尝试在 grails 3 1 11 中运行一个项目 但出现错误 失败 构建失败并出现异常 什么地方出了错 任务 bootRun 执行失败 进程 命令 C Program Files Java jdk1 8 0 111 bin java
  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • Mockito when().thenReturn 不必要地调用该方法

    我正在研究继承的代码 我编写了一个应该捕获 NullPointerException 的测试 因为它试图从 null 对象调用方法 Test expected NullPointerException class public void c
  • Spring @RequestMapping 带有可选参数

    我的控制器在请求映射中存在可选参数的问题 请查看下面的控制器 GetMapping produces MediaType APPLICATION JSON VALUE public ResponseEntity
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 将 List 转换为 JSON

    Hi guys 有人可以帮助我 如何将我的 HQL 查询结果转换为带有对象列表的 JSON 并通过休息服务获取它 这是我的服务方法 它返回查询结果列表 Override public List

随机推荐

  • 如何在 SQLite 查询中使用正则表达式?

    我想在 sqlite 中使用正则表达式 但我不知道如何 我的表有一列包含如下字符串 3 12 13 14 19 28 32 现在 如果我输入 where x LIKE 3 我还会得到包含 13 或 32 等值的行 但我只想获取该字符串中恰好
  • 以编程方式在 UITableViewCell 中呈现带有按钮的视图控制器 (Swift)

    I am trying to make it where when a user clicks on a table view cell in my table view it takes them to a new view contro
  • Outlook 插件 - 获取当前选定的日历日期

    当右键单击日历并运行功能区操作时 是否可以像获取当前邮件项或约会项一样获取选定的日历日期 功能区 XML
  • 是否可以将组件作为 props 传递并在 Vue 的子组件中使用它?

    在 Vue 2 0 应用程序中 假设我们有组件 A B 和 C A声明 注册并使用B 是否可以将C从A传递到B 像这样的事情
  • 如何取消numpy seed()的效果?

    我想在程序的第一部分使用 np random seed 并在第二部分取消它 再次 在我的 python 文件的第一部分中 我希望在每次执行时生成相同的随机数 在第二部分中 我希望在每次执行时生成不同的随机数 在第一部分中 使用常量初始化种子
  • Exchange Web 服务附件加载缓慢

    我正在编写一些代码来下载和处理电子邮件的附件 然后处理它们 该代码在某些情况下可以按要求工作 但仍然存在一些重大问题 每当代码将附件加载到本地磁盘上的文件中时 都会花费很长的时间 并且经常会由于下载缓慢而超时 并出现以下异常 A first
  • 意外查询成功

    SELECT COUNT FROM rps2 workflow WHERE workflow added gt TO DATE 01 09 2011 dd mm yyyy AND workflow finished lt TO DATE w
  • 如何将 system.data.SQLite.dll 的引用添加到 Windows Phone 7

    我是 Windows Phone 7 的新手 请帮我解决这个问题 我想在Windows Phone 7中添加SQLite数据库 我下载了system data SQLite dll 来自sourceforge www sqlite org
  • 蓝鸟承诺解析(数据)在客户端代码中未定义

    希亚斯 我有一个简单的应用程序 客户端期望得到一个承诺作为结果 但是在调用resolve 方法时 承诺不断返回未定义的结果 客户端代码 UsersRepo findOneAsync id id then function err resul
  • 为函数想出好的名字时遇到困难

    因此 我经常难以用简洁的名称描述函数 对于重用的功能来说 这通常不是问题 但通常需要将大型流程分解为子功能 这些通常会得到奇怪的名字 例如connectionsToAccessLines or handleWallVisionSplit或类
  • 在 C 预处理器中,“#”字符是否必须位于行的开头? [复制]

    这个问题在这里已经有答案了 我已经用 C 语言编程有一段时间了 在此期间 我了解到将预处理器指令之前的 字符放在第一列是一种常见的约定 Example include
  • 如何在 Foursquare Venues 搜索 API 中使用 CategoryId

    当包含categoryId参数时 我从API查询中得到了意外的结果 例如 当使用以下参数搜索马萨诸塞州波士顿的 The Citizen Public House 时 ll 42 3489027315987 71 096134185791 q
  • random.expovariate 相当于泊松过程

    我在某处读到 python 库函数 random expovariate 产生相当于泊松过程事件的间隔 真的是这样吗 或者我应该对结果施加一些其他功能 严格阅读你的问题 是的 这就是 random expovariate 所做的 expov
  • 什么是热点?

    我刚刚听说过 HotSpot JVM 而不是 Oracle JRockik JVM 什么是热点 这是旧的 Sun JVM 还是其他什么 HotSpot 是附带的 Sun JVM 它支持频繁使用的代码部分的即时编译 出于所有实际目的 它是 S
  • 如何从消息机器人中删除“Powered by ManyChat”页脚

    我正在为消息平台开发一个聊天机器人 但我发现自己对用户文本输入字段的页脚上出现的 ManyChat 感到着迷 我已成为该页面的管理员 并继续从该页面的已连接应用程序列表中删除许多聊天 但页脚仍然存在 也许我必须调用 Messenger 平台
  • 是否可以验证html5中input=file的大小和类型

    我正在读这个http dev w3 org html5 markup input file html http dev w3 org html5 markup input file html 但我只找到了 accept 属性 我试过这个
  • Python:检查对象是否是序列

    在 python 中 有没有一种简单的方法来判断某些东西是否不是序列 我尝试这样做 if x is not sequence但Python不喜欢那样 iter x 将提出一个TypeError if x不能迭代 但该检查 接受 集合和字典
  • 获取我的应用程序的当前 dot net 版本

    如何获取我的 asp net 应用程序的正在运行的 dot net 版本 我尝试了这里的解决方案 有没有一种简单的方法来检查 NET Framework 版本 https stackoverflow com questions 951856
  • 如何解决 HttpURLConnection 上的 NullPointerException?

    我正在开发一个Android应用程序 使用ExoPlayer进行视频播放 使用Glide进行图像显示 使用下载库进行文件下载 它们都有与HttpURLConnection相关的NullPointerException 我确信使用的链接是可用
  • Java中的BlockingQueue是完全线程安全的吗

    我知道文档说该对象是线程安全的 但这是否意味着从所有方法对它的所有访问都是线程安全的 所以如果我打电话put 同时从多个线程上进行操作take 在同一时刻 不会有什么不好的事情发生吗 我问这个问题是因为这个答案让我再次猜测 https st