| In Node.js, true multi-threading is not natively supported due to its single-threaded, event-driven architecture. However, you can achieve concurrency using worker threads and manage mutual exclusion using mechanisms like locks or atomic operations. Here’s how you can create a simple example of threads and mutual exclusion in Node.js using the worker_threads module and a basic lock mechanism: Step 1: Install Necessary Modules Ensure you have Node.js installed, as worker_threads is a built-in module starting from Node.js 10.5.0. Step 2: Create a Shared Resource with Mutual Exclusion File: counter.js // counter.js
let count = 0;
let lock = false;
function increment() {
while (lock) {
// Busy-wait (not ideal in real-world scenarios, but illustrates the concept)
}
lock = true;
count++;
lock = false;
return count;
}
module.exports = increment;
Step 3: Create a Worker Thread to Modify the Shared Resource File: worker.js // worker.js
const { parentPort } = require('worker_threads');
const increment = require('./counter');
parentPort.on('message', () => {
const newCount = increment();
parentPort.postMessage(newCount);
});
Step 4: Create the Main Thread to Spawn Worker Threads File: main.js // main.js
const { Worker } = require('worker_threads');
const numWorkers = 5;
for (let i = 0; i < numWorkers; i++) {
const worker = new Worker('./worker.js');
worker.on('message', (count) => {
console.log(`Worker ${i + 1}: Count is now ${count}`);
});
worker.postMessage('increment'); // Trigger the worker to increment the count
}
Explanation - Shared Resource (
counter.js):- This file defines a shared counter variable and a simple lock mechanism to prevent race conditions.
- The
increment() function increases the counter and ensures mutual exclusion using the lock variable.
- Worker Thread (
worker.js):- The worker listens for messages from the parent thread (
main.js) and increments the counter by calling the increment() function from counter.js. - The result is sent back to the parent thread.
- Main Thread (
main.js):- This file creates multiple worker threads.
- Each worker increments the shared counter and sends the updated value back to the main thread.
- The main thread logs the updated count to the console.
Step 5: Run the Application To run this example: node main.js
Output You should see output similar to: Worker 1: Count is now 1
Worker 2: Count is now 2
Worker 3: Count is now 3
Worker 4: Count is now 4
Worker 5: Count is now 5
Notes - Busy-Waiting: The
while (lock) {} loop in counter.js is a simple but inefficient method to implement mutual exclusion. In a real-world application, you would want to use more sophisticated techniques like Atomics or third-party libraries for locking mechanisms. - Concurrency, Not Parallelism: Node.js uses a single event loop for non-blocking I/O operations. The
worker_threads module provides a way to achieve parallelism by running JavaScript in separate threads, making it useful for CPU-bound tasks. - Avoid Race Conditions: The lock mechanism prevents race conditions in this example. In more complex applications, you'd use more advanced synchronization techniques.
This example demonstrates basic mutual exclusion in a multi-threaded Node.js environment using worker_threads. |