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.
[javascript]
let queue = [];
let threads = 100000;
for (let i = 0; i < threads; i++) {
setTimeout(() => {
queue.push(i);
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);
}
if (queue.length > 10) {
queue = queue.slice (1, 11);
}
if (i >= threads - 10) {
console.log(queue);
}
}, 1000);
}
[/javascript]
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.
[javascript]
let queue = [];
let threads = 100000;
for (let i = 0; i < threads; i++) {
setTimeout(() => {
queue.push(i);
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);
}
if (queue.length > 10) {
queue = tempQueue.slice (1, 11);
}
if (i >= threads - 10) {
console.log(queue);
}
}, 1000);
}
[/javascript]
Feng
没有评论:
发表评论