4

What is the exact consensus number of a multi-dequeuer queue?

I know that it is at least 2:
queue.enq(1)
queue.enq(0)
Thread A and B each call queue.deq().
The thread that got 1 will return it's own value.
The thread that got 0 will return the other's value.

But how do I prove it's exactly 2?
I think I should implement a queue using only 2-consensus objects, but I didn't manage to do it.

Luc M
  • 16,630
  • 26
  • 74
  • 89

2 Answers2

2

I think Adar Hefer's answer is correct. Still I kind of think, personal opinion, these formal answers are a pain.

As an informal answer. If you would have to get a consensus over multiple threads using a FIFO queue, how would you go about? So you can store three proposes, or more, no problem here. Than you can draw straws, either WIN, LOSE, or the second LOSE. Still no problem. But how do you get the correct 'voted upon' value? For a WIN you can just get your threadID, but how can you make sure both other threads also take the value of the winner? If you are a losing thread, from your standpoint you are unable to see which of the two other threads have won. All you know is that you've lost and should take an other proposed value. Gambling it away, you might draw the correct - you might not.

Khamaseen
  • 326
  • 3
  • 9
  • why can't the winner thread write its ID or the winning value to a shared variable and then everybody reads it from there? – ilstam Oct 25 '19 at 12:03
  • Well yes, totally possible. But, than it wouldn't just be a FIFO que. And the question would than be, how to solve this atomicly. Put a mutex(?), as after drawing you do need to store your number, but what if a thread halts? See where this is going? So the consensus number of a FIFO que is 2. – Khamaseen Oct 26 '19 at 21:27
  • Well, with the 2 threads you're using a proposed[] array too to store the values, so "it isn't just a queue" either. But I think to calculate the consensus number of an object you can take any number of instances of that object plus any number of atomic RW registers, so that's fine. Then is the real answer. I think there's no need for a mutex. Just the shared variable can be initialized to a value that if the other threads see, they know that it hasn't been updated yet by the winner and they can keep spinning on it. (Continued to next comment) – ilstam Oct 27 '19 at 08:09
  • The only real problem I see, is if the winner thread dies after picking the WIN straw but before updating the shared variable. – ilstam Oct 27 '19 at 08:11
  • But that makes me wonder. In case of 2 threads. What happens if one thread picks LOSE, and the second thread dies before even writing its own value in the proposed[] array? – ilstam Oct 27 '19 at 08:15
  • A thread writes it's value before drawing WIN or LOSE, that is why it wouldn't matter if a thread would die. Im unsure about how to translate "any number of atomic RW registers". E.g. you can always just place one AtomicStampRegister and with that solve for an infinite number of threads. atomicStampRegister(0, , , ). The first one to arrive will change the value with its own value. The rest just tries, fails, and eventually gets the value placed by the first thread. So, I'm not sure where that line is being drawn. – Khamaseen Oct 28 '19 at 09:35
  • Atomic registers as defined in the book The Art of Multiprocessor Programming: https://stackoverflow.com/questions/8871633/whats-the-difference-between-safe-regular-and-atomic-registers . Anyway. Right, a thread writes it's value before drawing/dequeuing. But my questions was, what about if the other thread dies? IE thread A writes its value then draws LOSE. Thread B dies straight away before even managing to propose/write its value. So, thread A knows it should use B's value, but B never proposed a value. Did we achieve consensus in that case? – ilstam Oct 28 '19 at 15:02
  • It is not possible to draw lose with only two threads if the winner did not wrote down its value. So A is the first to draw and wins. – Khamaseen Oct 29 '19 at 16:03
  • That book also talks about atomicregisters taking multiple values. Somewhere around 280+ – Khamaseen Oct 29 '19 at 16:13
  • You are absolutely right. I had misunderstood something. Thanks for the help clarifying it! – ilstam Oct 30 '19 at 06:03
1

Assume that it can solve consensus for 3 threads. Consider a critical state in a tree of all possible linearized concurrent executions. Take a left, and you'll decide 1. A right, and you'll decide 0.

Assume thread A deq()'s from the queue, and then B deq()'s from the queue. Now we took the left branch. Assume then that thread B deq()'s from the queue and then A deq()'s from the queue. Now we took the right branch.

Now if thread C deq()'s from the queue, it shouldn't care which of the others deq()'d first. The queue will look identical to it either way.

A contradiction: Thread C will decide 2 different things even though the execution is identical as far as it's concerned.

Adar Hefer
  • 1,514
  • 1
  • 12
  • 18