From d9584646389001606626e1517ea6abb5e38ca455 Mon Sep 17 00:00:00 2001 From: Vladyslav Karpenko Date: Tue, 14 Feb 2023 17:22:40 +0200 Subject: [PATCH] Enhance livelock example More complex but clear to notice livelock test: - 7 threads - 6 of it executes high frequency loop - last 7th thread executes low frequency loop with long running process - initial 10 times frequency difference do not lead to livelock - comment with proposal to make frequency difference 100 times higher which will lead to livelock Signed-off-by: Vladyslav Karpenko --- JavaScript/3-livelock.js | 41 +++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/JavaScript/3-livelock.js b/JavaScript/3-livelock.js index 70ce7bd..373df06 100644 --- a/JavaScript/3-livelock.js +++ b/JavaScript/3-livelock.js @@ -3,6 +3,8 @@ const threads = require('node:worker_threads'); const { Worker, isMainThread } = threads; +const THREADS_COUNT = 7; + const LOCKED = 0; const UNLOCKED = 1; @@ -37,24 +39,49 @@ if (isMainThread) { const mutex1 = new Mutex(buffer, 0, true); const mutex2 = new Mutex(buffer, 4, true); console.dir({ mutex1, mutex2 }); - new Worker(__filename, { workerData: buffer }); - new Worker(__filename, { workerData: buffer }); + for (let i = 0; i < THREADS_COUNT; i++) new Worker(__filename, { workerData: buffer }); } else { const { threadId, workerData } = threads; const mutex1 = new Mutex(workerData); const mutex2 = new Mutex(workerData, 4); - const loop = () => { + const lowFrequencyLoop = (delay) => { + mutex1.enter(() => { + console.log(`Some useful processing from worker${threadId} based on data locked by mutex1`); + mutex2.enter(() => { + console.log(`Some useful processing from worker${threadId} based on data locked by mutex2`); + setTimeout(() => { + mutex1.leave(); + console.log(`Left mutex1 from worker${threadId} after some useful process has been done`); + mutex2.leave(); + console.log(`Left mutex2 from worker${threadId} after some useful process has been done`); + setTimeout(lowFrequencyLoop, delay, delay); + }, 2000); + }); + }); + }; + + const highFrequencyLoop = (delay) => { mutex1.enter(() => { console.log(`Entered mutex1 from worker${threadId}`); - if (mutex1.leave()) console.log(`Left mutex1 from worker${threadId}`); + mutex1.leave(); + console.log(`Left mutex1 from worker${threadId}`); }); mutex2.enter(() => { console.log(`Entered mutex2 from worker${threadId}`); - if (mutex2.leave()) console.log(`Left mutex2 from worker${threadId}`); + mutex2.leave(); + console.log(`Left mutex2 from worker${threadId}`); }); - setTimeout(loop, 0); + setTimeout(highFrequencyLoop, delay, delay); }; - loop(); + if (threadId === THREADS_COUNT) { + // Only one thread executes low frequent process + lowFrequencyLoop(1000); + } else { + // All other threads executes high frequent processes + highFrequencyLoop(100); + // Try to change delay between iterations to 1 ms + // Look out how livelock preventing useful low frequent process to get access on data locked by Mutex + } }