जावास्क्रिप्ट में कंकरेंसी और मल्टीथ्रेडिंग: एडवांस्ड लेवल

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

जावास्क्रिप्ट में कंकरेंसी और मल्टीथ्रेडिंग: एडवांस्ड लेवल

\n\n

जावास्क्रिप्ट को पारंपरिक रूप से एक सिंगल-थ्रेडेड भाषा माना जाता है, लेकिन आधुनिक Node.js इकोसिस्टम कंकरेंसी और वास्तविक मल्टीथ्रेडिंग के लिए शक्तिशाली टूल प्रदान करता है। इस लेख में हम एडवांस्ड तकनीकों को समझेंगे: Event Loop की बारीकियों से लेकर Worker Threads, SharedArrayBuffer और Atomics के उपयोग तक। आप लोड को कुशलतापूर्वक वितरित करना, रेस कंडीशन से बचना और स्केलेबल एप्लिकेशन बनाना सीखेंगे।

\n\n

1. Event Loop, माइक्रोटास्क और मैक्रोटास्क: कंकरेंसी की नींव

\n\n

Event Loop को समझना बिना ब्लॉकिंग के कंकरेंसी को मैनेज करने की कुंजी है। Node.js में इवेंट लूप कई चरणों में विभाजित है: टाइमर, I/O कॉलबैक, idle, poll, check (setImmediate) और close। माइक्रोटास्क (Promise, process.nextTick) और मैक्रोटास्क (setTimeout, setInterval, I/O) के बीच अंतर करना महत्वपूर्ण है।

\n\n

माइक्रोटास्क वर्तमान चरण के पूरा होने के तुरंत बाद, अगले मैक्रोटास्क से पहले निष्पादित होते हैं। यदि माइक्रोटास्क अनंत रूप से उत्पन्न होते हैं, तो यह Event Loop को "भूखा" कर सकता है।

\n\n
// उदाहरण: माइक्रोटास्क मैक्रोटास्क को ब्लॉक कर रहे हैं\nsetTimeout(() => console.log('मैक्रोटास्क'), 0);\n\nPromise.resolve().then(() => {\n  // अनंत माइक्रोटास्क\n  process.nextTick(() => {\n    console.log('माइक्रोटास्क');\n    // रिकर्सिव कॉल Event Loop को ब्लॉक कर देगा\n    process.nextTick(() => process.nextTick(() => {}));\n  });\n});\n// आउटपुट: 'माइक्रोटास्क' (अनंत), 'मैक्रोटास्क' कभी निष्पादित नहीं होगा
\n\n

एडवांस्ड कंट्रोल के लिए queueMicrotask() और setImmediate() का उपयोग करें। याद रखें: process.nextTick को Promise माइक्रोटास्क से पहले प्राथमिकता मिलती है।

\n\n

2. Worker Threads: Node.js में वास्तविक मल्टीथ्रेडिंग

\n\n

worker_threads मॉड्यूल आपको समानांतर थ्रेड्स में जावास्क्रिप्ट निष्पादित करने की अनुमति देता है। प्रत्येक Worker का अपना V8 इंस्टेंस और अलग मेमोरी होती है। डेटा का आदान-प्रदान संदेशों या SharedArrayBuffer के माध्यम से होता है।

\n\n

एक सरल Worker बनाना:

\n\n
// main.js\nconst { Worker } = require('worker_threads');\n\nfunction runWorker(file, data) {\n  return new Promise((resolve, reject) => {\n    const worker = new Worker(file, { workerData: data });\n    worker.on('message', resolve);\n    worker.on('error', reject);\n    worker.on('exit', (code) => {\n      if (code !== 0) reject(new Error(`Worker कोड ${code} के साथ रुका`));\n    });\n  });\n}\n\n// चलाएं\nrunWorker('./worker.js', { iterations: 1e9 })\n  .then(result => console.log('परिणाम:', result))\n  .catch(err => console.error(err));
\n\n
// worker.js\nconst { parentPort, workerData } = require('worker_threads');\n\nfunction heavyComputation(n) {\n  let sum = 0;\n  for (let i = 0; i < n; i++) { sum += Math.sqrt(i); }\n  return sum;\n}\n\nparentPort.postMessage(heavyComputation(workerData.iterations));
\n\n

महत्वपूर्ण: Worker के पास DOM, प्रक्रिया के ग्लोबल ऑब्जेक्ट (process.env) और मुख्य थ्रेड में लोड किए गए मॉड्यूल तक पहुंच नहीं है। केवल सीरियलाइज़ेबल डेटा ही भेजें।

\n\n

Worker पूल

\n

प्रत्येक कार्य के लिए Worker बनाना महंगा है। पूल का उपयोग करें:

\n\n
class WorkerPool {\n  constructor(file, size = 4) {\n    this.workers = [];\n    this.queue = [];\n    for (let i = 0; i < size; i++) {\n      const worker = new Worker(file);\n      worker.on('message', (result) => this._handleResult(worker, result));\n      worker.on('error', (err) => this._handleError(worker, err));\n      this.workers.push(worker);\n    }\n  }\n\n  runTask(data) {\n    return new Promise((resolve, reject) => {\n      this.queue.push({ data, resolve, reject });\n      this._processQueue();\n    });\n  }\n\n  _processQueue() {\n    if (this.queue.length === 0) return;\n    const worker = this.workers.find(w => !w.busy);\n    if (!worker) return;\n    worker.busy = true;\n    const task = this.queue.shift();                

ब्लॉग

पुस्तक अनुशंसाएँ