【问题标题】:Wait-free queue implementation in JAVAJAVA中的无等待队列实现
【发布时间】:2015-12-21 09:43:57
【问题描述】:

我一直在尝试使用 Alex KoganErez Petrankhere 获取的已编写的免等待队列,但遇到了问题。我无法理解在第 5 页和第 7 页的 que()deque() 方法中需要使用确切的线程 ID:

void enq(int value) {
    long phase = maxPhase() + 1; // cf. Figure 3b
    state.set(TID, new
        OpDesc(phase, true, true, new Node(value, TID)));
    help(phase);
    help finish enq();
}

还有

int deq() throws EmptyException {
    long phase = maxPhase() + 1; // cf. Figure 5a
    state.set(TID, new OpDesc(phase, true, false, null));
    help(phase);
    help finish deq();
    Node node = state.get(TID).node;
    if (node == null) {
        throw new EmptyException();
    }
    return node.next.get().value;
}

应该使用什么线程ID?

【问题讨论】:

  • “ID”代表唯一标识符。线程 ID 的基本要求是每个线程都必须有一个,并且每个线程的 ID 必须与其他每个线程的 ID 不同,并且一个线程的 ID 永远不能改变。对于任何 Java 线程 tt.getId() 返回的数字将满足这些要求。

标签: java multithreading queue theory wait-free


【解决方案1】:

在论文中他们说 TID 是 int 范围内的 [0, . . . , NUM THRDS−1].,所以看起来它是一个手动分配的数字。

我没有读过论文,所以我不知道是否有严格要求只能使用符合本规范的标识符。 java.lang.Thread 上有一个 long getId() 方法。见Javadoc for Thread.getId()

返回此线程的标识符。线程 ID 是创建此线程时生成的正长整数。线程 ID 是唯一的,并且在其生命周期内保持不变。当一个线程被终止时,这个线程ID可能会被重用。

您可以使用它而不是自己分配 TID。

【讨论】:

    【解决方案2】:

    我不得不说,考虑到 JDK 中的所有队列选择并发包,我不相信你选择这样一个非标准的队列实现。

    首先,从您发布的方法来看,deq() 方法的最差性能很差。它会在队列为空时引发异常,这对于任何需要这种无等待队列的应用程序来说都是非常昂贵的。

    其次,论文中的性能测量是基于动态分配的队列;其中内存分配碎片和页面错误将是这里的主要性能损失。实际上,可以通过peak arrival rate * peak lasting period 轻松估计正常情况下的最大队列长度,并将队列设置为静态分配该容量。生产者试图让队列已满的任何情况都可以简单地暂停(并且不太可能发生)。即使发生这种情况,线程停放的性能损失通常以 1 毫秒为单位。

    如果您在实际生产系统中寻找小于 1 毫秒的延迟,Java 可能不是适合您的工具。如果没有精细调整的内存对齐,即使有可能,也很难做到这一点。是的,LMAX 是用 Disruptor 做到的,但恕我直言,它只是通过向 JVM 添加一些自定义内存管理包来实现的。

    所以从所有实践的角度来看,你应该在 JDK 中使用标准队列,或者转向 Disruptor,或者使用 C/C++。这种具有未经证实的实现的数据结构本身并不是一个正确的选择。

    【讨论】:

    • 感谢您的回答,相信您提供了合理的答案。我只是想比较不同的实现。
    • 我明白了。从这样的角度来看,添加到此类结构中的线程 ID 几乎与 ThreadLocal 队列实例相同。就像您通过线程 ID 进行散列一样,将来自某个线程的事件始终放入同一个队列中,并由另一个线程处理该队列。这样的结构是可以的,但唯一的问题是你需要有一个从 ID 到队列的静态散列策略。如果您有 1 或 2 个线程总是产生大量事件,并且您碰巧将它们散列在一起,您可能会遇到性能问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-13
    • 2013-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    相关资源
    最近更新 更多