I am going to add a global queue object to my nodejs express program, then this raises a concern of thread safety.
I am implementing a queue with only 10 elements, the older elements will be throw away. So I wrote the following code to test.
In the following code, the if (queue.length > 10) can cause problem. Because when both thread run into this block and both finish pushing the element, we will have 12 elements in the queue.
For example
[12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]
The new elements in this queue is 22, and 23.
Now thread 1 will do a slice and make the queue to be
[13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
At this point, because the queue length is 10, then the thread 2 will not do the slice. The pushed element 23 is gone.
If thread 2 read the queue length before thread 1 slice it. Then thread 2 will slice it again.
the array become
[14, 15, 16, 17, 18, 19, 20, 21, 22]
Only 9 element in the queue, 13 is gone.
let queue = []; let threads = 100000; for (let i = 0; i < threads; i++) { setTimeout(() => { queue.push(i); // This line can have a dirty read if (queue.length > 10) { queue = queue.slice (1, 11); } if (i >= threads - 10) { console.log(queue); } }, 1000); }
But when I tested this in the browser. it never failed. It’s very interesting.
A small improvement is using a temp variable to hold the original queue outside the if block, then use the temp var in the if block. It will make sure only 1 element will be missing.
let queue = []; let threads = 100000; for (let i = 0; i < threads; i++) { setTimeout(() => { queue.push(i); let tempQueue = queue; // This line can have a dirty read if (queue.length > 10) { queue = tempQueue.slice (1, 11); } if (i >= threads - 10) { console.log(queue); } }, 1000); }