0

I've been trying to use already written Wait-free queue by Alex Kogan and Erez Petrank taken from here, but faced the problem. I can't understand that exactly thread ID need to be used in que() and deque() methods on page 5 and 7:

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();
}

And

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;
}

What thread id should used?

Rocketq
  • 5,423
  • 23
  • 75
  • 126
  • 1
    "ID" stands for _unique IDentifier_. The basic requirements for a thread ID are that every thread has to have one, and every thread's ID has to be different from every other thread's ID, and a thread's ID can never change. For any Java thread `t`, the number returned by `t.getId()` will meet those requirements. – Solomon Slow Dec 21 '15 at 13:56
  • This is what I tried back when I attempted to implement this paper https://github.com/mrhampson/WaitFreeQueue – Marshall Hampson Aug 24 '22 at 04:37

2 Answers2

1

In the paper they says that TID is an int in the range [0, . . . , NUM THRDS−1]., so it looks like it is a manually assigned number.

I've not read the paper, so I don't know if there is a strict requirement only to use an identifier meeting this specification. There is a long getId() method on java.lang.Thread. See the Javadoc for Thread.getId():

Returns the identifier of this Thread. The thread ID is a positive long number generated when this thread was created. The thread ID is unique and remains unchanged during its lifetime. When a thread is terminated, this thread ID may be reused.

You may be able to use this instead of assigning the TIDs yourself.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
1

I have to say I am not convinced by your choosing such a non-standard queue implementation given all the queue choices concurrency package in JDK.

Firstly, from the method you posted, the worst performance of the deq() method is poor. It throws exception upon queue empty which is utterly expensive for any application which needs such a wait free queue.

Secondly the performance measurement in the paper is based on dynamically allocated queue; where memory allocation fragmentation and page fault would be the major performance penalty here. In reality, one can easily estimate the normal case maximum queue length by peak arrival rate * peak lasting period and set the queue to be statically allocated with that capacity. Any case the producer is trying to put with queue full can simply be suspended (and is very unlikely to happen). Even if such scenario happens, the performance penalty of thread parking is usually in terms of 1 millisecond.

In case you are looking for delay of less than 1 millisecond in a real-world production system, Java is probably not the right tool for you. Without fine-turned memory alignment, it's very difficult if any possible to achieve so. Yes LMAX did it with Disruptor but IMHO only by adding some custom memory management packages to JVM.

So from all practice perspective, you should either use standard queues in JDK, or turn to Disruptor, or use C/C++. This data structure itself with a unproven implementation is just no a right choice.

Alex Suo
  • 2,977
  • 1
  • 14
  • 22
  • Thank for your answer, I believe you provided reasonable answer. I'm just want to compare different implementations. – Rocketq Dec 21 '15 at 10:22
  • 1
    I see. In such a perspective, the thread ID adding to such a structure is almost identical to a `ThreadLocal` queue instance. It's just as you hash by the thread ID to put the events from a certain thread always into one same queue, and process the queue by another thread. Such structure is OK but only problem of it is you need to have a static hashing strategy from the IDs to the queues. If you have 1 or 2 threads always producing large number of events, and you happen to hash them together, you might encounter performance problem. – Alex Suo Dec 21 '15 at 10:28