यह संभव नहीं है कि दो (या अधिक) धागे एक ही समय में लॉक का अधिग्रहण करें। उदाहरण के लिए सिंक्रनाइज़ेशन विधियों के कुछ प्रकार हैं:
सक्रिय प्रतीक्षा - स्पिन लॉक
स्यूडोकोड:
1. while ( xchg(lock, 1) == 1); - entry protocole
XCHG परमाणु ऑपरेशन (x86 आर्किटेक्चर पर मौजूद) का एक उदाहरण है, जो पहले "लॉक" वेरिएबल के लिए नया मान सेट करता है और उसके बाद दूसरा वैल्यू देता है। परमाणु का मतलब यह है कि यह नए मूल्य निर्धारित करने और पुराने वापस लौटने के बीच के उदाहरण में बाधित नहीं हो सकता है। परमाणु - नियतात्मक परिणाम चाहे जो भी हो।
2. Your code
3. lock = 0; - exit protocol
जब ताला 0 के बराबर होता है तो एक और धागा महत्वपूर्ण खंड में प्रवेश कर सकता है - जबकि लूप समाप्त होता है।
थ्रेड सस्पेंडिंग - उदाहरण के लिए सेमाफोर की गिनती
दो परमाणु आपरेशन भी बना हुआ है .Wait()
और .Signal()
और पूर्णांक चर इसे कहते देता है हमारे पास int currentValue
।
Wait():
if (currentValue > 0) currentValue -= 1;
else suspend current thread;
Signal():
If there exists thread suspended by semaphore wake up one of them
Else currentValue += 1;
अब महत्वपूर्ण खंड समस्या को हल करना वास्तव में आसान है:
स्यूडोकोड:
mySemaphore.Wait();
do some operations - critical section
mySemaphore.Signal();
आमतौर पर आपके प्रोग्रामिंग थ्रेड एपीआई आपको सेमीफोर महत्वपूर्ण अनुभाग में अधिकतम समवर्ती धागे को निर्दिष्ट करने की क्षमता प्रदान करना चाहिए। स्पष्ट रूप से मल्टीथ्रेडेड सिस्टम (म्यूटेक्स, मॉनिटर, बाइनरी सेमाफोर आदि) में अधिक प्रकार के सिंक्रनाइज़ेशन हैं, लेकिन वे उपरोक्त विचारों पर आधारित हैं। कोई यह तर्क दे सकता है कि थ्रेड सस्पेंड करने वाले तरीकों को सक्रिय प्रतीक्षा के लिए प्राथमिकता दी जानी चाहिए (इसलिए सीपीयू व्यर्थ नहीं है) - यह हमेशा सच नहीं है। जब थ्रेड निलंबित किया जा रहा है - संदर्भ स्विच नामक महंगा ऑपरेशन इसे जगह लेता है। हालाँकि यह उचित है जब प्रतीक्षा समय कम हो (धागे की संख्या ~ कोर की संख्या)।