CodeGym /Java Blog /अनियमित /थ्रेड तुल्यकालन। सिंक्रनाइज़ ऑपरेटर
John Squirrels
स्तर 41
San Francisco

थ्रेड तुल्यकालन। सिंक्रनाइज़ ऑपरेटर

अनियमित ग्रुप में प्रकाशित
नमस्ते! आज हम मल्टीथ्रेडेड प्रोग्रामिंग की विशेषताओं पर विचार करना जारी रखेंगे और थ्रेड सिंक्रोनाइज़ेशन के बारे में बात करेंगे। थ्रेड तुल्यकालन।  सिंक्रोनाइज़्ड ऑपरेटर - 1

जावा में तुल्यकालन क्या है?

प्रोग्रामिंग डोमेन के बाहर, इसका तात्पर्य एक ऐसी व्यवस्था से है जो दो उपकरणों या कार्यक्रमों को एक साथ काम करने की अनुमति देती है। उदाहरण के लिए, एक स्मार्टफोन और कंप्यूटर को Google खाते के साथ सिंक्रोनाइज़ किया जा सकता है, और एक वेबसाइट अकाउंट को सोशल नेटवर्क अकाउंट्स के साथ सिंक्रोनाइज़ किया जा सकता है ताकि आप साइन इन करने के लिए उनका उपयोग कर सकें। थ्रेड सिंक्रोनाइज़ेशन का एक समान अर्थ है: यह एक व्यवस्था है जिसमें थ्रेड्स इंटरैक्ट करते हैं एक-दूसरे से। पिछले पाठों में, हमारे धागे एक दूसरे से अलग रहते थे और काम करते थे। एक ने गणना की, दूसरा सो गया, और तीसरे ने कंसोल पर कुछ प्रदर्शित किया, लेकिन उन्होंने बातचीत नहीं की। वास्तविक कार्यक्रमों में, ऐसी स्थितियाँ दुर्लभ होती हैं। एकाधिक थ्रेड सक्रिय रूप से एक ही डेटा सेट के साथ काम कर सकते हैं और संशोधित कर सकते हैं। इससे समस्याएं पैदा होती हैं। एक ही स्थान पर पाठ लिखने वाले कई थ्रेड्स की कल्पना करें, उदाहरण के लिए, टेक्स्ट फ़ाइल या कंसोल पर। इस स्थिति में, फ़ाइल या कंसोल एक साझा संसाधन बन जाता है। धागे एक-दूसरे के अस्तित्व से अनजान हैं, इसलिए वे थ्रेड शेड्यूलर द्वारा आवंटित समय में वे सब कुछ लिख सकते हैं जो वे कर सकते हैं। हाल ही के एक पाठ में, हमने इसका एक उदाहरण देखा कि यह किस ओर जाता है। आइए अब इसे याद करें: थ्रेड तुल्यकालन।  सिंक्रोनाइज़्ड ऑपरेटर - 2कारण इस तथ्य में निहित है कि धागे एक दूसरे के साथ अपने कार्यों को समन्वयित किए बिना एक साझा संसाधन (कंसोल) के साथ काम कर रहे हैं। यदि थ्रेड शेड्यूलर थ्रेड -1 को समय आवंटित करता है, तो यह तुरंत सब कुछ कंसोल पर लिखता है। अन्य धागे क्या हैं या पहले से ही लिखने में कामयाब नहीं हुए हैं, इससे कोई फर्क नहीं पड़ता। परिणाम, जैसा कि आप देख सकते हैं, निराशाजनक है। इसलिए उन्होंने मल्टीथ्रेडेड प्रोग्रामिंग के लिए एक विशेष अवधारणा, म्यूटेक्स (पारस्परिक बहिष्करण) की शुरुआत की। एक म्यूटेक्स का उद्देश्यएक तंत्र प्रदान करना है ताकि एक निश्चित समय में केवल एक धागे की किसी वस्तु तक पहुंच हो। यदि थ्रेड-1 ऑब्जेक्ट ए के म्यूटेक्स को प्राप्त करता है, तो अन्य थ्रेड्स ऑब्जेक्ट को एक्सेस और संशोधित करने में सक्षम नहीं होंगे। ऑब्जेक्ट ए के म्यूटेक्स जारी होने तक अन्य धागे को इंतजार करना होगा। यहाँ जीवन से एक उदाहरण दिया गया है: कल्पना करें कि आप और 10 अन्य अजनबी एक अभ्यास में भाग ले रहे हैं। बदले में, आपको अपने विचार व्यक्त करने और कुछ पर चर्चा करने की आवश्यकता है। लेकिन क्योंकि आप पहली बार एक-दूसरे को देख रहे हैं, इसलिए लगातार एक-दूसरे को बाधित न करने और गुस्से में उड़ने के लिए, आप 'टॉकिंग बॉल' का उपयोग करते हैं: केवल वही व्यक्ति बोल सकता है जिसके पास गेंद है। इस तरह आप एक अच्छी और फलदायी चर्चा समाप्त करते हैं। अनिवार्य रूप से, गेंद एक म्युटेक्स है। यदि किसी वस्तु का म्यूटेक्स एक धागे के हाथों में है, तो अन्य धागे वस्तु के साथ काम नहीं कर सकते।Objectवर्ग, जिसका अर्थ है कि जावा में प्रत्येक वस्तु में एक है।

सिंक्रोनाइज़्ड ऑपरेटर कैसे काम करता है

आइए एक नए कीवर्ड के बारे में जानें: सिंक्रोनाइज़्ड । इसका उपयोग कोड के एक निश्चित ब्लॉक को चिह्नित करने के लिए किया जाता है। यदि एक कोड ब्लॉक को synchronizedकीवर्ड के साथ चिह्नित किया गया है, तो उस ब्लॉक को एक समय में केवल एक थ्रेड द्वारा निष्पादित किया जा सकता है। सिंक्रनाइज़ेशन को विभिन्न तरीकों से लागू किया जा सकता है। उदाहरण के लिए, संपूर्ण विधि को सिंक्रनाइज़ करने की घोषणा करके:

public synchronized void doSomething() {

   // ...Method logic
}
या एक कोड ब्लॉक लिखें जहां किसी वस्तु का उपयोग करके सिंक्रनाइज़ेशन किया जाता है:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...Some logic available simultaneously to all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
अर्थ सरल है। यदि एक थ्रेड कीवर्ड के साथ चिह्नित कोड ब्लॉक के अंदर जाता है synchronized, तो यह ऑब्जेक्ट के म्यूटेक्स को तुरंत पकड़ लेता है, और उसी ब्लॉक या विधि में प्रवेश करने की कोशिश करने वाले अन्य सभी थ्रेड्स को तब तक इंतजार करने के लिए मजबूर किया जाता है जब तक कि पिछला थ्रेड अपना काम पूरा नहीं कर लेता और मॉनिटर जारी नहीं कर देता। थ्रेड तुल्यकालन।  सिंक्रोनाइज़्ड ऑपरेटर - 3वैसे! कोर्स के दौरान, आप पहले ही के उदाहरण देख चुके हैं synchronized, लेकिन वे अलग दिखे:

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
विषय आपके लिए नया है। और, ज़ाहिर है, सिंटैक्स के साथ भ्रम होगा। इसलिए, इसे लिखने के विभिन्न तरीकों से बाद में भ्रमित होने से बचने के लिए इसे तुरंत याद कर लें। इसे लिखने के इन दो तरीकों का मतलब एक ही है:

public void swap() {

   synchronized (this)
   {
       // ...Method logic
   }
}


public synchronized void swap() {

   }
}
पहले मामले में, आप विधि में प्रवेश करने के तुरंत बाद कोड का एक सिंक्रनाइज़ ब्लॉक बना रहे हैं। यह thisवस्तु, यानी वर्तमान वस्तु द्वारा सिंक्रनाइज़ किया जाता है। और दूसरे उदाहरण में, आप synchronizedकीवर्ड को पूरी विधि पर लागू करते हैं। यह सिंक्रनाइज़ेशन के लिए उपयोग की जा रही वस्तु को स्पष्ट रूप से इंगित करने के लिए अनावश्यक बनाता है। चूंकि संपूर्ण विधि कीवर्ड के साथ चिह्नित है, इसलिए कक्षा के सभी उदाहरणों के लिए विधि स्वचालित रूप से सिंक्रनाइज़ हो जाएगी। हम इस चर्चा में नहीं पड़ेंगे कि कौन सा तरीका बेहतर है। अभी के लिए, जो भी तरीका आपको सबसे अच्छा लगे उसे चुनें :) मुख्य बात यह याद रखना है: आप एक विधि को केवल तभी घोषित कर सकते हैं जब उसके सभी तर्क एक समय में एक थ्रेड द्वारा निष्पादित किए जाते हैं। उदाहरण के लिए, निम्न विधि को सिंक्रनाइज़ करना एक गलती होगी doSomething():

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...Some logic available simultaneously to all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
जैसा कि आप देख सकते हैं, विधि के भाग में तर्क शामिल है जिसे सिंक्रनाइज़ेशन की आवश्यकता नहीं है। उस कोड को एक ही समय में कई थ्रेड्स द्वारा चलाया जा सकता है, और सभी महत्वपूर्ण स्थानों को एक अलग synchronizedब्लॉक में अलग रखा जाता है। और एक और बात। आइए नाम की अदला-बदली वाले पाठ से हमारे उदाहरण की बारीकी से जाँच करें:

public void swap()
{
   synchronized (this)
   {
       // ...Method logic
   }
}
नोट: तुल्यकालन का उपयोग करके किया जाता हैthis। अर्थात् किसी विशिष्टMyClassवस्तु का उपयोग करना। मान लीजिए कि हमारे पास 2 धागे (Thread-1औरThread-2) और केवल एकMyClass myClassवस्तु है। इस स्थिति में, यदिThread-1कॉल किया जाता हैmyClass.swap(), तो ऑब्जेक्ट का म्यूटेक्स व्यस्त हो जाएगा, औरम्यूटेक्स के रिलीज़ होने की प्रतीक्षा करते समयmyClass.swap()विधि कोThread-2यदि हमारे पास 2 थ्रेड्स और 2MyClassऑब्जेक्ट्स (myClass1औरmyClass2) हैं, तो हमारे थ्रेड्स अलग-अलग ऑब्जेक्ट्स पर सिंक्रोनाइज़्ड मेथड्स को आसानी से एक साथ निष्पादित कर सकते हैं। पहला धागा इसे निष्पादित करता है:

myClass1.swap();
दूसरा इसे निष्पादित करता है:

myClass2.swap();
इस मामले में, विधि synchronizedके अंदर का कीवर्ड swap()प्रोग्राम के संचालन को प्रभावित नहीं करेगा, क्योंकि एक विशिष्ट वस्तु का उपयोग करके सिंक्रनाइज़ेशन किया जाता है। और बाद के मामले में, हमारे पास 2 वस्तुएँ हैं। इस प्रकार, धागे एक दूसरे के लिए समस्याएँ पैदा नहीं करते हैं। आखिरकार, दो वस्तुओं में 2 अलग-अलग म्यूटेक्स होते हैं, और एक प्राप्त करना दूसरे को प्राप्त करने से स्वतंत्र होता है

स्थैतिक विधियों में तुल्यकालन की विशेष विशेषताएं

लेकिन क्या होगा यदि आपको स्थिर विधि को सिंक्रनाइज़ करने की आवश्यकता है ?

class MyClass {
   private static String name1 = "Ally";
   private static String name2 = "Lena";

   public static synchronized void swap() {
       String s = name1;
       name1 = name2;
       name2 = s;
   }

}
यह स्पष्ट नहीं है कि म्यूटेक्स यहाँ क्या भूमिका निभाएगा। आखिरकार, हमने पहले ही निर्धारित कर लिया है कि प्रत्येक वस्तु में एक म्यूटेक्स है। लेकिन समस्या यह है कि हमें MyClass.swap()विधि को कॉल करने के लिए वस्तुओं की आवश्यकता नहीं है: विधि स्थिर है! अब अगला क्या होगा? :/यहाँ वास्तव में कोई समस्या नहीं है। जावा के रचनाकारों ने सब कुछ का ख्याल रखा :) यदि महत्वपूर्ण समवर्ती तर्क वाली विधि स्थिर है, तो कक्षा स्तर पर सिंक्रनाइज़ेशन किया जाता है। अधिक स्पष्टता के लिए, हम उपरोक्त कोड को निम्नानुसार फिर से लिख सकते हैं:

class MyClass {
   private static String name1 = "Ally";
   private static String name2 = "Lena";

   public static void swap() {

       synchronized (MyClass.class) {
           String s = name1;
           name1 = name2;
           name2 = s;
       }
   }

}
सिद्धांत रूप में, आप स्वयं इसके बारे में सोच सकते थे: क्योंकि कोई वस्तु नहीं है, तुल्यकालन तंत्र को किसी तरह कक्षा में ही बेक किया जाना चाहिए। और यह ऐसा ही है: हम सिंक्रनाइज़ करने के लिए कक्षाओं का उपयोग कर सकते हैं।
टिप्पणियां
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION