【问题标题】:BlockingQueues and thread access order阻塞队列和线程访问顺序
【发布时间】:2013-08-30 08:09:27
【问题描述】:

我有一种情况,多个线程将通过调用take() 轮询单个BlockingQueue。我想知道的是:

如果多个线程正在等待队列接收一个项目,它们是否会按照它们调用take() 的顺序优先从队列中取出项目,或者线程将其取出的顺序是什么?队列是任意的?

谢谢!

注意:过去我已经为这种事情编写了自己的实现,但我想知道 Java 中的 BlockingQueue 实现是否会为我做这件事。

【问题讨论】:

  • 一般来说,任何多线程应用程序都不应该对线程执行的顺序做任何假设。有一些方法可以强制执行,但 MT 应用程序背后的想法是不应该这样做。
  • 有趣的问题,我已经编写并运行了一个程序 - 没有固定的顺序。
  • Related question 也讨论了公平性。

标签: java multithreading queue


【解决方案1】:

这取决于实现,一个类是否支持对等待的生产者和消费者线程进行排序的可选公平策略。例如。 ArrayBlockingQueue 可以是公平的,因为它有构造函数 ArrayBlockingQueue(int capacity, boolean fair),但是 LinkedBlockingQueue 不能。

【讨论】:

    【解决方案2】:

    这取决于实现。

    如果您使用LinkedBlockingQueuetake() 方法将使用ReentrantLock 进行检查

    public E take() throws InterruptedException {
        E x;
        int c = -1;
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lockInterruptibly();
        ...
    }
    
    // declared as
    private final ReentrantLock takeLock = new ReentrantLock(); // no fairness argument, defaults to false
    

    javadoc

    这个类的构造函数接受一个可选的公平参数。 当设置为 true 时,在争用情况下,锁倾向于授予对 等待时间最长的线程。 否则此锁不保证任何 特定的访问顺序。使用许多人访问的公平锁的程序 线程可能会显示较低的整体吞吐量(即较慢;通常 慢得多)比那些使用默认设置,但有更小的 获得锁和保证没有饥饿的时间差异。 但是请注意,锁的公平性并不能保证锁的公平性 线程调度。因此,使用公平锁的许多线程之一可能 连续多次获取,同时其他活动线程 没有进展并且当前没有持有锁。另请注意, untimed tryLock 方法不遵守公平设置。它会 即使其他线程正在等待,如果锁可用,则成功。

    【讨论】:

      【解决方案3】:

      在许多情况下,javadocs 会提到该类是否“公平”,即阻塞是分布式的,以便所有线程获得相同的机会。然而,这并不一定意味着与“以相同的顺序”相同。检查您的特定队列实现的 javadocs 以查看它是否包含有关公平和/或顺序的信息。

      至少ArrayBlockingQueue 告知公平性如下:

      这个类支持一个可选的排序等待公平策略 生产者和消费者线程。默认情况下,此排序不是 保证。但是,将公平性设置为 true 构造的队列 以 FIFO 顺序授予线程访问权限。公平性普遍下降 吞吐量,但减少可变性并避免饥饿。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-13
        • 2014-10-16
        • 2019-02-12
        • 2018-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多