You can simplify the algorithm:
do { waiting[i] = true; while (waiting[i] && test_and_set(&lock)) ; waiting[i] = false; j = (i + 1) % n; while ((j != i) && !waiting[j]) j = (j + 1) % n; if (j == i) lock = false; else waiting[j] = false; } while (true);
and that would be exactly the same. I think the authors used key because they thought this would make the code easier to read.
As stated in the comments:
Typically, when using test_and_set you simply do while(test_and_set(&lock)) ; . However, in this case, you want to make sure that the thread only waits a limited amount of time to block. This is done using the waiting array. At the end of the critical section, when we unlock, we do not just set the lock to false, as you usually unlock it. Instead, we try to find the next thread that is waiting for blocking. To the next, I mean the increment of the stream identifier, and then the cycle when we press n (part j = (j + 1) % n; ). If such a stream j found, we set waiting[j] to false instead of lock .
This prevents scenarios in which 2 or more threads are constantly locking up while another thread or thread group is always waiting. For example, let's say that 3 threads expect the same lock (threads 0, 1, and 2). Say thread 0 releases the lock, and then thread 1 captures it. While thread 1 has lock thread 0, then tries to lock again, and when thread 1 releases lock thread 0, it locks it instead of thread 2. This can be repeated endlessly and thread 2 never gets a lock.
In this limited wait algorithm using the waiting array, this behavior cannot occur. If three threads constantly capture a lock, the next thread in terms of a thread identifier will go further, for example. thread 0 will capture and release the lock, followed by thread 1, and then thread 2. This is because each thread expects either a lock or its entry in the waiting array becomes false . If another thread is waiting for a lock when the thread is about to release the lock, it sets the waiting entry instead of lock , freeing only that thread from waiting for rotation. This prevents the pathological event of one or more threads waiting indefinitely to block.
missimer
source share