नमस्ते! जब आपने CodeGym पर मल्टीथ्रेडिंग का अध्ययन किया, तो आपको अक्सर "म्यूटेक्स" और "मॉनिटर" की अवधारणाओं का सामना करना पड़ा। बिना देखे, क्या आप कह सकते हैं कि वे कैसे भिन्न हैं? :) यदि हाँ, शाबाश! यदि नहीं (यह सबसे आम है), तो इसमें कोई आश्चर्य की बात नहीं है। "म्यूटेक्स" और "मॉनिटर" वास्तव में संबंधित अवधारणाएं हैं। इसके अतिरिक्त, जब आप पाठ पढ़ते हैं और अन्य वेबसाइटों पर मल्टीथ्रेडिंग के बारे में वीडियो देखते हैं, तो आप एक अन्य समान अवधारणा से परिचित होंगे: "सेमाफोर"। यह मॉनिटर और म्यूटेक्स के समान कार्य भी करता है। इसलिए हम इन तीन शर्तों की जांच करने जा रहे हैं। हम कुछ उदाहरण देखेंगे और निश्चित रूप से समझेंगे कि ये अवधारणाएँ एक दूसरे से कैसे भिन्न हैं :)
दूसरे शब्दों में, एक समय में केवल एक थ्रेड साझा संसाधनों के साथ काम कर सकता है। अन्य थ्रेड्स (लोगों) द्वारा कब्जे वाले संसाधनों तक पहुंच प्राप्त करने का प्रयास विफल हो जाएगा। एक म्यूटेक्स में कई महत्वपूर्ण विशेषताएं हैं। सबसे पहले , केवल दो राज्य संभव हैं: "अनलॉक" और "लॉक"। इससे हमें यह समझने में मदद मिलती है कि यह कैसे काम करता है: आप बूलियन वैरिएबल (सही/गलत) या बाइनरी नंबर (0/1) के साथ समानताएं बना सकते हैं। , राज्य को सीधे नियंत्रित नहीं किया जा सकता है। जावा में कोई तंत्र नहीं है जो आपको स्पष्ट रूप से एक वस्तु लेने, उसका म्यूटेक्स प्राप्त करने और वांछित स्थिति प्रदान करने देगा। दूसरे शब्दों में, आप ऐसा कुछ नहीं कर सकते:
जावा में सेमाफोर को सेमाफोर वर्ग द्वारा दर्शाया जाता है। सेमाफोर ऑब्जेक्ट बनाते समय, हम निम्नलिखित कंस्ट्रक्टर का उपयोग कर सकते हैं:
समझने में सुविधा के लिए, हम इसे थोड़ा सरल करेंगे। कल्पना कीजिए कि हमारे पास 5 दार्शनिक हैं जिन्हें दोपहर का खाना खाने की जरूरत है। इसके अतिरिक्त, हमारे पास एक टेबल है जो एक साथ दो से अधिक लोगों को समायोजित नहीं कर सकती है। हमारा काम सभी दार्शनिकों को खिलाना है। उनमें से किसी को भी भूखा नहीं रहना चाहिए, और मेज पर बैठने की कोशिश करते समय उनमें से किसी को भी एक-दूसरे को "ब्लॉक" नहीं करना चाहिए (हमें गतिरोध से बचना चाहिए)। यहाँ हमारा दार्शनिक वर्ग कैसा दिखेगा:
अंतर केवल इतना है कि एक वस्तु का म्यूटेक्स एक समय में केवल एक धागे द्वारा प्राप्त किया जा सकता है, जबकि एक सेमाफोर के मामले में, जो एक थ्रेड काउंटर का उपयोग करता है, कई धागे एक साथ संसाधन तक पहुंच सकते हैं। यह सिर्फ एक संयोग नहीं है :) एक म्यूटेक्स वास्तव में एक सेमाफोर है1 की गिनती के साथ। दूसरे शब्दों में, यह एक सेमाफोर है जो एक धागे को समायोजित कर सकता है। इसे "बाइनरी सेमाफोर" के रूप में भी जाना जाता है क्योंकि इसके काउंटर में केवल 2 मान हो सकते हैं - 1 ("अनलॉक") और 0 ("लॉक")। इतना ही! जैसा कि आप देख सकते हैं, यह इतना भ्रमित करने वाला नहीं है :) अब, यदि आप इंटरनेट पर अधिक विस्तार से मल्टीथ्रेडिंग का अध्ययन करना चाहते हैं, तो आपके लिए इन अवधारणाओं को नेविगेट करना थोड़ा आसान हो जाएगा। अगले पाठों में मिलते हैं!
म्युटेक्स
थ्रेड्स को सिंक्रनाइज़ करने के लिए एक म्यूटेक्स (या लॉक) एक विशेष तंत्र है। जावा में प्रत्येक वस्तु के लिए एक "संलग्न" है - आप पहले से ही जानते हैं कि :) इससे कोई फर्क नहीं पड़ता कि आप मानक वर्गों का उपयोग करते हैं या अपनी खुद की कक्षाएं बनाते हैं, उदाहरण के लिए बिल्ली और कुत्ता : सभी वर्गों की सभी वस्तुओं में एक म्यूटेक्स होता है । "म्यूटेक्स" शब्द "म्युचुअल एक्सक्लूज़न" से आया है, जो इसके उद्देश्य का पूरी तरह से वर्णन करता है। जैसा कि हमने अपने पिछले पाठों में कहा था, एक म्यूटेक्स यह सुनिश्चित करना संभव बनाता है कि एक समय में केवल एक थ्रेड के पास ऑब्जेक्ट तक पहुंच हो। म्यूटेक्स के एक लोकप्रिय वास्तविक जीवन उदाहरण में शौचालय शामिल हैं। जब कोई व्यक्ति शौचालय के विभाजन में प्रवेश करता है, तो वह दरवाजे को अंदर से बंद कर लेता है। शौचालय एक वस्तु की तरह है जिसे कई धागों से एक्सेस किया जा सकता है। विभाजन के दरवाजे पर ताला एक म्यूटेक्स की तरह है, और बाहर के लोगों की पंक्ति धागे का प्रतिनिधित्व करती है। दरवाजे पर लगा ताला शौचालय का म्यूटेक्स है: यह सुनिश्चित करता है कि केवल एक ही व्यक्ति अंदर जा सकता है।![म्यूटेक्स, मॉनिटर और सेमाफोर के बीच क्या अंतर है? - 2](https://cdn.codegym.cc/images/article/85889d2a-5fc1-4f1f-b316-44b2d67779f9/800.jpeg)
Object myObject = new Object();
Mutex mutex = myObject.getMutex();
mutex.free();
इसका अर्थ है कि आप किसी वस्तु का म्युटेक्स जारी नहीं कर सकते हैं। केवल जावा मशीन की ही इस तक सीधी पहुंच है। प्रोग्रामर म्यूटेक्स के साथ भाषा के उपकरणों के माध्यम से काम करते हैं।
निगरानी करना
एक म्यूटेक्स पर एक मॉनिटर एक अतिरिक्त "सुपरस्ट्रक्चर" है। वास्तव में, एक मॉनिटर कोड का एक हिस्सा है जो प्रोग्रामर के लिए "अदृश्य" होता है। जब हमने पहले म्यूटेक्स के बारे में बात की थी, तो हमने एक सरल उदाहरण दिया था:public class Main {
private Object obj = new Object();
public void doSomething() {
// ...some logic, available for all threads
synchronized (obj) {
// Logic available to just one thread at a time
}
}
}
सिंक्रनाइज़ किए गए कीवर्ड के साथ चिह्नित कोड ब्लॉक में , हमारे ओबीजे ऑब्जेक्ट का म्यूटेक्स प्राप्त किया जाता है। बढ़िया, हम ताला प्राप्त कर सकते हैं, लेकिन वास्तव में "सुरक्षा" कैसे प्रदान की जाती है? जब हम शब्द सिंक्रनाइज़ देखते हैं , तो अन्य थ्रेड्स को ब्लॉक में प्रवेश करने से क्या रोकता है? सुरक्षा मॉनिटर से आती है! कंपाइलर सिंक्रोनाइज़्ड कीवर्ड को कोड के कई विशेष टुकड़ों में बदल देता है। एक बार फिर से, doSomething() मेथड के साथ अपने उदाहरण पर वापस आते हैं । हम इसमें जोड़ देंगे:
public class Main {
private Object obj = new Object();
public void doSomething() {
// ...some logic, available for all threads
// Logic available to just one thread at a time
synchronized (obj) {
/* Do important work that requires that the object
be accessed by only one thread */
obj.someImportantMethod();
}
}
}
संकलक द्वारा इस कोड को परिवर्तित करने के बाद "हुड के नीचे" क्या होता है:
public class Main {
private Object obj = new Object();
public void doSomething() throws InterruptedException {
// ...some logic, available for all threads
// Logic available to just one thread at a time:
/* as long as the object's mutex is busy,
all the other threads (except the one that acquired it) are put to sleep */
while (obj.getMutex().isBusy()) {
Thread.sleep(1);
}
// Mark the object's mutex as busy
obj.getMutex().isBusy() = true;
/* Do important work that requires that the object
be accessed by only one thread */
obj.someImportantMethod();
// Free the object's mutex
obj.getMutex().isBusy() = false;
}
}
बेशक, यह एक वास्तविक उदाहरण नहीं है। यहां, हमने जावा मशीन के अंदर क्या होता है, यह दर्शाने के लिए जावा-जैसे कोड का उपयोग किया। उस ने कहा, यह छद्म कोड इस बात की उत्कृष्ट समझ देता है कि सिंक्रोनाइज़्ड ब्लॉक के अंदर ऑब्जेक्ट और थ्रेड्स के साथ वास्तव में क्या होता है और कैसे कंपाइलर इस कीवर्ड को प्रोग्रामर के लिए "अदृश्य" कई स्टेटमेंट में बदल देता है। मूल रूप से, जावा मॉनिटर का प्रतिनिधित्व करने के लिए सिंक्रोनाइज़्ड कीवर्ड का उपयोग करता है । पिछले उदाहरण में सिंक्रोनाइज़्ड कीवर्ड के बजाय दिखाई देने वाला सभी कोड मॉनिटर है।
सिकंदरा
एक और शब्द जो आपको मल्टीथ्रेडिंग के अपने व्यक्तिगत अध्ययन में मिलेगा वह है "सेमाफोर"। आइए जानें कि यह क्या है और यह मॉनिटर और म्यूटेक्स से कैसे भिन्न है। एक सेमाफोर कुछ संसाधन तक पहुंच को सिंक्रनाइज़ करने का एक उपकरण है। इसकी विशिष्ट विशेषता यह है कि यह तुल्यकालन तंत्र बनाने के लिए एक काउंटर का उपयोग करता है। काउंटर हमें बताता है कि कितने धागे एक साथ साझा संसाधन तक पहुंच सकते हैं।![म्यूटेक्स, मॉनिटर और सेमाफोर के बीच क्या अंतर है? - 3](https://cdn.codegym.cc/images/article/edf6d093-dd70-41a0-8e8d-b987e687c089/800.jpeg)
Semaphore(int permits)
Semaphore(int permits, boolean fair)
हम कंस्ट्रक्टर को निम्नलिखित पास करते हैं:
- बूलियन फेयर - उस क्रम को स्थापित करता है जिसमें थ्रेड्स एक्सेस प्राप्त करेंगे। यदि उचित सत्य है, तो वेटिंग थ्रेड्स को उस क्रम में पहुंच प्रदान की जाती है जिसमें उन्होंने इसका अनुरोध किया था। यदि यह गलत है, तो ऑर्डर थ्रेड शेड्यूलर द्वारा निर्धारित किया जाता है।
![म्यूटेक्स, मॉनिटर और सेमाफोर के बीच क्या अंतर है? - 4](https://cdn.codegym.cc/images/article/4c00491f-3890-4989-85bb-4533c33c7750/800.jpeg)
class Philosopher extends Thread {
private Semaphore sem;
// Did the philosopher eat?
private boolean full = false;
private String name;
Philosopher(Semaphore sem, String name) {
this.sem=sem;
this.name=name;
}
public void run()
{
try
{
// If the philosopher has not eaten
if (!full) {
// Ask the semaphore for permission to run
sem.acquire();
System.out.println(name + " takes a seat at the table");
// The philosopher eats
sleep(300);
full = true;
System.out.println(name + " has eaten! He leaves the table");
sem.release();
// The philosopher leaves, making room for others
sleep(300);
}
}
catch(InterruptedException e) {
System.out.println("Something went wrong!");
}
}
}
और यहाँ हमारे प्रोग्राम को चलाने के लिए कोड है:
public class Main {
public static void main(String[] args) {
Semaphore sem = new Semaphore(2);
new Philosopher(sem, "Socrates").start();
new Philosopher(sem,"Plato").start();
new Philosopher(sem,"Aristotle").start();
new Philosopher(sem, "Thales").start();
new Philosopher(sem, "Pythagoras").start();
}
}
हमने शर्त को पूरा करने के लिए एक सेमाफोर बनाया जिसका काउंटर 2 पर सेट है: केवल दो दार्शनिक एक ही समय में खा सकते हैं। यही है, एक ही समय में केवल दो धागे चल सकते हैं, क्योंकि हमारे दार्शनिक वर्ग को थ्रेड विरासत में मिला है ! सेमाफोर वर्ग के अधिग्रहण () और रिलीज () तरीके इसके एक्सेस काउंटर को नियंत्रित करते हैं। अधिग्रहण () विधि सेमाफोर को संसाधन तक पहुंचने के लिए कहती है। यदि काउंटर> 0 है, तो पहुंच प्रदान की जाती है और काउंटर 1 से कम हो जाता है। रिलीज़ ()विधि पहले दी गई पहुंच को "रिलीज़" करती है, इसे काउंटर पर लौटाती है (सेमाफोर के एक्सेस काउंटर को 1 से बढ़ा देती है)। जब हम प्रोग्राम चलाते हैं तो हमें क्या मिलता है? क्या समस्या हल हो गई है? क्या हमारे दार्शनिक अपनी बारी का इंतजार करते हुए नहीं लड़ेंगे? :) यहाँ हमें मिला कंसोल आउटपुट है:
Socrates takes a seat at the table
Plato takes a seat at the table
Socrates has eaten! He leaves the table
Plato has eaten! He leaves the table
Aristotle takes a seat at the table
Pythagoras takes a seat at the table
Aristotle has eaten! He leaves the table
Pythagoras has eaten! He leaves the table
Thales takes a seat at the table
Thales has eaten! He leaves the table
हमने यह किया! और हालांकि थेल्स को अकेले भोजन करना पड़ा, मुझे नहीं लगता कि हमने उसे नाराज किया है :) आपने म्यूटेक्स और सेमाफोर के बीच कुछ समानताएं देखी होंगी। दरअसल, उनका एक ही मिशन है: किसी संसाधन तक पहुंच को सिंक्रनाइज़ करना। ![म्यूटेक्स, मॉनिटर और सेमाफोर के बीच क्या अंतर है? - 5](https://cdn.codegym.cc/images/article/79101c56-64fa-4482-8591-f4467b482298/800.jpeg)