0

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

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?

4

2 回答 2

1

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

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

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

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

于 2015-12-21T09:54:18.293 回答
1

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

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

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

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

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

于 2015-12-21T10:18:26.127 回答