मल्टीथ्रेडिंग Python उदाहरण के साथ: GIL सीखें Python
⚡ स्मार्ट सारांश
मल्टीथ्रेडिंग Python यह एक ही प्रोसेस के अंदर कई थ्रेड्स चलाता है ताकि वे मेमोरी साझा कर सकें और एक साथ काम कर सकें। थ्रेडिंग मॉड्यूल इन थ्रेड्स को बनाता और प्रबंधित करता है, जबकि ग्लोबल इंटरप्रेटर लॉक वास्तविक समानांतरता को सीमित करता है, जिससे यह तकनीक इनपुट/आउटपुट-आधारित कार्यों के लिए सबसे उपयुक्त है।

RSI Python प्रोग्रामिंग भाषा आपको मल्टीप्रोसेसिंग या मल्टीथ्रेडिंग का उपयोग करने की अनुमति देती है। इस ट्यूटोरियल में, आप मल्टीथ्रेडेड एप्लिकेशन लिखना सीखेंगे। Python.
एक धागा क्या है?
थ्रेड समवर्ती प्रोग्रामिंग में निष्पादन की एक इकाई है। मल्टीथ्रेडिंग एक ऐसी तकनीक है जो सीपीयू को एक ही प्रक्रिया के कई कार्यों को एक साथ निष्पादित करने की अनुमति देती है। ये थ्रेड अपने प्रोसेस संसाधनों को साझा करते हुए व्यक्तिगत रूप से निष्पादित हो सकते हैं।
प्रक्रिया क्या है?
प्रोसेस मूल रूप से चल रहे प्रोग्राम को कहते हैं। जब आप अपने कंप्यूटर पर कोई एप्लिकेशन (जैसे ब्राउज़र या टेक्स्ट एडिटर) शुरू करते हैं, तो ऑपरेटिंग सिस्टम एक प्रोसेस बनाता है। प्रक्रिया.
मल्टीथ्रेडिंग क्या है? Python?
मल्टीथ्रेडिंग Python मल्टीथ्रेडिंग एक सुप्रसिद्ध तकनीक है जिसमें एक प्रक्रिया में कई थ्रेड मुख्य थ्रेड के साथ अपना डेटा स्पेस साझा करते हैं, जिससे थ्रेड्स के बीच सूचना साझाकरण और संचार आसान और कुशल हो जाता है। थ्रेड्स प्रक्रियाओं की तुलना में हल्के होते हैं। कई थ्रेड अपने प्रोसेस संसाधनों को साझा करते हुए व्यक्तिगत रूप से निष्पादित हो सकते हैं। मल्टीथ्रेडिंग का उद्देश्य एक ही समय में कई कार्यों और कार्यों को चलाना है।
मल्टीप्रोसेसिंग क्या है?
बहु आपको एक साथ कई असंबंधित प्रक्रियाएँ चलाने की अनुमति देता है। ये प्रक्रियाएँ अपने संसाधनों को साझा नहीं करती हैं और IPC के माध्यम से संचार करती हैं।
Python मल्टीथ्रेडिंग बनाम मल्टीप्रोसेसिंग
प्रोसेस और थ्रेड को समझने के लिए, इस उदाहरण पर विचार करें: आपके कंप्यूटर पर मौजूद एक .exe फ़ाइल एक प्रोग्राम है। जब आप इसे खोलते हैं, तो ऑपरेटिंग सिस्टम इसे मेमोरी में लोड करता है और CPU इसे निष्पादित करता है। इस समय चल रहे प्रोग्राम के इंस्टेंस को प्रोसेस कहा जाता है।
प्रत्येक प्रक्रिया के दो मूलभूत घटक होते हैं:
- RSI Code
- आँकड़े
अब, एक प्रक्रिया में एक या एक से अधिक उप-भाग हो सकते हैं जिन्हें कहा जाता है धागे। यह ऑपरेटिंग सिस्टम के आर्किटेक्चर पर निर्भर करता है। आप थ्रेड को प्रोसेस के एक ऐसे हिस्से के रूप में समझ सकते हैं जिसे ऑपरेटिंग सिस्टम द्वारा अलग से निष्पादित किया जा सकता है।
दूसरे शब्दों में, यह निर्देशों की एक ऐसी श्रृंखला है जिसे ऑपरेटिंग सिस्टम द्वारा स्वतंत्र रूप से चलाया जा सकता है। एक ही प्रक्रिया के भीतर मौजूद थ्रेड उस प्रक्रिया के डेटा को साझा करते हैं और समानांतर संचालन को सुगम बनाने के लिए एक साथ काम करने के लिए डिज़ाइन किए गए हैं।
मल्टीथ्रेडिंग का उपयोग क्यों करें?
मल्टीथ्रेडिंग आपको किसी एप्लिकेशन को कई उप-कार्यों में विभाजित करने और इन कार्यों को एक साथ चलाने की अनुमति देता है। यदि आप मल्टीथ्रेडिंग का सही तरीके से उपयोग करते हैं, तो आपके एप्लिकेशन की गति, प्रदर्शन और रेंडरिंग सभी में सुधार हो सकता है।
Python multithreading
Python यह मल्टीप्रोसेसिंग और मल्टीथ्रेडिंग दोनों के लिए संरचनाओं का समर्थन करता है। इस ट्यूटोरियल में, आप मुख्य रूप से कार्यान्वयन पर ध्यान केंद्रित करेंगे। बहु के साथ अनुप्रयोग Pythonथ्रेड्स को संभालने के लिए दो मुख्य मॉड्यूल का उपयोग किया जा सकता है। Python:
- RSI धागा मॉड्यूल, और
- RSI सूत्रण मॉड्यूल
हालांकि, में Pythonइसके अलावा, ग्लोबल इंटरप्रेटर लॉक (GIL) नामक एक चीज़ भी होती है। इससे प्रदर्शन में कोई खास सुधार नहीं होता और शायद इससे प्रदर्शन और भी खराब हो सकता है। को कम करने कुछ मल्टीथ्रेडेड अनुप्रयोगों का प्रदर्शन। आप इस ट्यूटोरियल के आगामी अनुभागों में इसके बारे में सब कुछ सीखेंगे।
थ्रेड और थ्रेडिंग मॉड्यूल
इस ट्यूटोरियल में आप जिन दो मॉड्यूल के बारे में जानेंगे वे हैं धागा मॉड्यूल और थ्रेडिंग मॉड्यूल.
हालाँकि, थ्रेड मॉड्यूल को लंबे समय से हटा दिया गया है। Python 3, इसे अप्रचलित घोषित कर दिया गया है और इसे केवल इस रूप में ही उपयोग किया जा सकता है _धागा पिछड़ी संगतता के लिए।
आपको उच्च-स्तर का उपयोग करना चाहिए सूत्रण यह मॉड्यूल उन अनुप्रयोगों के लिए है जिन्हें आप तैनात करना चाहते हैं। थ्रेड मॉड्यूल को यहां केवल शैक्षिक उद्देश्यों के लिए शामिल किया गया है।
थ्रेड मॉड्यूल
इस मॉड्यूल का उपयोग करके नया थ्रेड बनाने का सिंटैक्स इस प्रकार है:
thread.start_new_thread(function_name, arguments)
ठीक है, अब आपने कोडिंग शुरू करने के लिए बुनियादी सिद्धांत को कवर कर लिया है। तो, अपना खोलें IDLE या नोटपैड लें और निम्नलिखित टाइप करें:
import time import _thread def thread_test(name, wait): i = 0 while i <= 3: time.sleep(wait) print("Running %s\n" %name) i = i + 1 print("%s has finished execution" %name) if __name__ == "__main__": _thread.start_new_thread(thread_test, ("First Thread", 1)) _thread.start_new_thread(thread_test, ("Second Thread", 2)) _thread.start_new_thread(thread_test, ("Third Thread", 3))
फ़ाइल को सेव करें और प्रोग्राम को चलाने के लिए F5 दबाएँ। अगर सब कुछ सही तरीके से किया गया है, तो आपको यह आउटपुट दिखाई देगा:
आगामी अनुभागों में आप रेस की स्थितियों और उनसे निपटने के तरीकों के बारे में अधिक जानेंगे।
कोड स्पष्टीकरण
- ये कथन टाइम और थ्रेड मॉड्यूल को आयात करते हैं, जिनका उपयोग निष्पादन और विलंब को संभालने के लिए किया जाता है। Python धागे।
- यहाँ, आपने एक फ़ंक्शन परिभाषित किया है जिसे थ्रेड_टेस्ट, जिसे बुलाया जाएगा नया_धागा_शुरू_करें यह फ़ंक्शन एक while लूप को चार बार चलाता है और इसे कॉल करने वाले थ्रेड का नाम प्रिंट करता है। लूप पूरा होने पर, यह एक संदेश प्रिंट करता है जिसमें बताया जाता है कि थ्रेड का निष्पादन समाप्त हो गया है।
- यह आपके प्रोग्राम का मुख्य भाग है। यहाँ, आप बस कॉल करते हैं नया_धागा_शुरू_करें के साथ विधि थ्रेड_टेस्ट आप थ्रेड_टेस्ट फ़ंक्शन को आर्गुमेंट के रूप में पास कर सकते हैं। इससे आर्गुमेंट के रूप में पास किए गए फ़ंक्शन के लिए एक नया थ्रेड बनेगा और वह चलना शुरू हो जाएगा। ध्यान दें कि आप इसे (थ्रेड_टेस्ट) किसी भी अन्य फ़ंक्शन से बदल सकते हैं जिसे आप थ्रेड के रूप में चलाना चाहते हैं।
थ्रेडिंग मॉड्यूल
यह मॉड्यूल थ्रेडिंग का उच्च-स्तरीय कार्यान्वयन है। Python और यह मल्टीथ्रेडेड एप्लिकेशन को प्रबंधित करने का सर्वमान्य तरीका है। थ्रेड मॉड्यूल की तुलना में यह कई प्रकार की सुविधाएँ प्रदान करता है।
थ्रेडिंग मॉड्यूल की संरचना
इस मॉड्यूल में परिभाषित कुछ उपयोगी कार्यों की सूची यहां दी गई है:
| फ़ंक्शन का नाम | विवरण |
|---|---|
| सक्रिय गणना() | की गिनती लौटाता है धागा वे वस्तुएँ जो अभी भी जीवित हैं। |
| वर्तमान थ्रेड() | थ्रेड वर्ग का वर्तमान ऑब्जेक्ट लौटाता है। |
| गणना करें() | सभी सक्रिय थ्रेड ऑब्जेक्ट्स को सूचीबद्ध करता है. |
| isडेमन() | यदि थ्रेड डेमॉन है तो true लौटाता है. |
| जिंदा है() | यदि थ्रेड अभी भी जीवित है तो true लौटाता है। |
| थ्रेड क्लास विधियाँ | |
| शुरू() | किसी थ्रेड की गतिविधि शुरू करता है। इसे प्रत्येक थ्रेड के लिए केवल एक बार ही कॉल किया जाना चाहिए क्योंकि इसे कई बार कॉल करने पर रनटाइम त्रुटि आएगी। |
| Daud() | यह विधि थ्रेड की गतिविधि को दर्शाती है और इसे थ्रेड क्लास का विस्तार करने वाले क्लास द्वारा ओवरराइड किया जा सकता है। |
| में शामिल होने के () | यह अन्य कोड के निष्पादन को तब तक अवरुद्ध करता है जब तक कि वह थ्रेड समाप्त नहीं हो जाता जिस पर join() विधि को बुलाया गया था। |
बैकस्टोरी: थ्रेड क्लास
थ्रेडिंग मॉड्यूल का उपयोग करके मल्टीथ्रेडेड प्रोग्राम कोडिंग शुरू करने से पहले, थ्रेड क्लास को समझना अत्यंत महत्वपूर्ण है। थ्रेड क्लास वह प्राथमिक क्लास है जो किसी थ्रेड के टेम्पलेट और उसके संचालन को परिभाषित करती है। Python.
मल्टीथ्रेडेड बनाने का सबसे आम तरीका Python इस एप्लिकेशन का उद्देश्य एक ऐसी क्लास घोषित करना है जो थ्रेड क्लास का विस्तार करती है और उसके रन() मेथड को ओवरराइड करती है।
संक्षेप में, थ्रेड क्लास एक कोड अनुक्रम को दर्शाता है जो एक अलग तरीके से चलता है धागा नियंत्रण के।
इसलिए, मल्टीथ्रेडेड ऐप लिखते समय, आप निम्नलिखित कार्य करेंगे:
- एक ऐसी क्लास को परिभाषित करें जो थ्रेड क्लास का विस्तार करती हो।
- ओवरराइड किया __init__ निर्माता
- ओवरराइड किया Daud() तरीका
एक बार थ्रेड ऑब्जेक्ट बना लेने के बाद, शुरू() इस गतिविधि के निष्पादन को शुरू करने के लिए विधि का उपयोग किया जा सकता है, और में शामिल होने के () विधि का उपयोग वर्तमान गतिविधि समाप्त होने तक अन्य सभी कोड को ब्लॉक करने के लिए किया जा सकता है।
अब, आइए आपके पिछले उदाहरण को लागू करने के लिए थ्रेडिंग मॉड्यूल का उपयोग करने का प्रयास करें। एक बार फिर, अपना मॉड्यूल शुरू करें। IDLE और निम्नलिखित टाइप करें:
import time import threading class threadtester (threading.Thread): def __init__(self, id, name, i): threading.Thread.__init__(self) self.id = id self.name = name self.i = i def run(self): thread_test(self.name, self.i, 5) print ("%s has finished execution " %self.name) def thread_test(name, wait, i): while i: time.sleep(wait) print ("Running %s \n" %name) i = i - 1 if __name__=="__main__": thread1 = threadtester(1, "First Thread", 1) thread2 = threadtester(2, "Second Thread", 2) thread3 = threadtester(3, "Third Thread", 3) thread1.start() thread2.start() thread3.start() thread1.join() thread2.join() thread3.join()
जब आप उपरोक्त कोड निष्पादित करेंगे तो यह आउटपुट होगा:
कोड स्पष्टीकरण
- यह भाग हमारे पिछले उदाहरण के समान है। यहाँ, आप टाइम और थ्रेड मॉड्यूल आयात करते हैं, जिनका उपयोग निष्पादन और विलंब को संभालने के लिए किया जाता है। Python धागे।
- इस भाग में, आप थ्रेडटेस्टर नामक एक क्लास बना रहे हैं, जो थ्रेडटेस्टर को इनहेरिट या एक्सटेंड करता है। धागा थ्रेडिंग मॉड्यूल का एक वर्ग। थ्रेड बनाने के सबसे सामान्य तरीकों में से एक यह है। Pythonहालाँकि, आपको केवल कंस्ट्रक्टर और को ही ओवरराइड करना चाहिए। Daud() अपने ऐप में विधि। जैसा कि आप ऊपर दिए गए कोड नमूने में देख सकते हैं, __init__ विधि (कंस्ट्रक्टर) को ओवरराइड कर दिया गया है। इसी तरह, आपने भी ओवरराइड कर दिया है Daud() विधि। इसमें वह कोड होता है जिसे आप थ्रेड के अंदर निष्पादित करना चाहते हैं। इस उदाहरण में, आपने thread_test() फ़ंक्शन को कॉल किया है।
- यह thread_test() विधि है, जो मान लेती है i एक तर्क के रूप में, यह प्रत्येक पुनरावृति में इसे 1 से घटाता है, और शेष कोड को तब तक दोहराता है जब तक कि i शून्य न हो जाए। प्रत्येक पुनरावृति में, यह वर्तमान में चल रहे थ्रेड का नाम प्रिंट करता है और wait सेकंड के लिए रुकता है (जिसे एक तर्क के रूप में भी लिया जाता है)।
- thread1 = threadtester(1, “पहला थ्रेड”, 1) यहाँ, हम एक थ्रेड बना रहे हैं और तीन पैरामीटर पास कर रहे हैं जिन्हें हमने __init__ में घोषित किया है। पहला पैरामीटर थ्रेड की आईडी है, दूसरा पैरामीटर थ्रेड का नाम है, और तीसरा पैरामीटर काउंटर है, जो यह निर्धारित करता है कि while लूप को कितनी बार चलाना चाहिए।
- thread2.start() मेथड का उपयोग थ्रेड के निष्पादन को शुरू करने के लिए किया जाता है। आंतरिक रूप से, start() फ़ंक्शन आपकी क्लास के run() मेथड को कॉल करता है।
- thread3.join() join() विधि अन्य कोड के निष्पादन को अवरुद्ध करती है और उस थ्रेड के समाप्त होने तक प्रतीक्षा करती है जिस पर उसे बुलाया गया था।
जैसा कि आप जानते ही हैं, एक ही प्रक्रिया में मौजूद थ्रेड्स उस प्रक्रिया की मेमोरी और डेटा तक पहुंच रखते हैं। परिणामस्वरूप, यदि एक से अधिक थ्रेड एक साथ डेटा को बदलने या एक्सेस करने का प्रयास करते हैं, तो त्रुटियां उत्पन्न हो सकती हैं।
अगले भाग में, आप उन विभिन्न प्रकार की जटिलताओं को देखेंगे जो तब उत्पन्न हो सकती हैं जब थ्रेड्स मौजूदा एक्सेस लेनदेन की जांच किए बिना डेटा और क्रिटिकल सेक्शन तक पहुंचते हैं।
गतिरोध और दौड़ की स्थिति
डेडलॉक और रेस कंडीशन के बारे में जानने से पहले, समवर्ती प्रोग्रामिंग से संबंधित कुछ बुनियादी परिभाषाओं को समझना सहायक होगा:
- महत्वपूर्ण अनुभाग: यह कोड का एक अंश है जो साझा चरों तक पहुंचता है या उन्हें संशोधित करता है और इसे एक परमाणु लेनदेन के रूप में निष्पादित किया जाना चाहिए।
- संदर्भ स्विच: यह वह प्रक्रिया है जिसका पालन सीपीयू एक कार्य से दूसरे कार्य में बदलने से पहले थ्रेड की स्थिति को संग्रहीत करने के लिए करता है ताकि बाद में उसी बिंदु से कार्य को फिर से शुरू किया जा सके।
गतिरोध
गतिरोध समवर्ती/मल्टीथ्रेडेड एप्लिकेशन लिखते समय डेवलपर्स को जिन सबसे बड़ी समस्याओं का सामना करना पड़ता है, उनमें से एक है 'समवर्ती/मल्टीथ्रेडेड' समस्या। Pythonडेडलॉक को समझने का सबसे अच्छा तरीका कंप्यूटर विज्ञान के क्लासिक उदाहरण समस्या का उपयोग करना है जिसे डेडलॉक के नाम से जाना जाता है। भोजन Philoसोफ़र्स समस्या.
भोजन दार्शनिकों के लिए समस्या कथन इस प्रकार है:
चित्र में दिखाए अनुसार, पांच दार्शनिक एक गोल मेज पर बैठे हैं, जिस पर स्पेगेटी (एक प्रकार का पास्ता) की पांच प्लेटें और पांच कांटे रखे हैं।
भोजन Philoसोफ़र्स समस्या
किसी भी समय एक दार्शनिक या तो खा रहा होता है या सोच रहा होता है।
इसके अलावा, एक दार्शनिक को स्पेगेटी खाने से पहले अपने बगल के दो कांटे (यानी, बाएं और दाएं कांटे) लेने चाहिए। गतिरोध की समस्या तब होती है जब सभी पांच दार्शनिक एक साथ अपने दाएं कांटे उठाते हैं।
चूँकि सभी दार्शनिकों के पास एक-एक कांटा है, इसलिए वे सभी दूसरों के कांटा नीचे रखने का इंतज़ार करेंगे। नतीजतन, उनमें से कोई भी स्पेगेटी नहीं खा पाएगा।
इसी तरह, एक समवर्ती प्रणाली में, डेडलॉक तब होता है जब विभिन्न थ्रेड या प्रक्रियाएँ (दार्शनिक) एक ही समय में साझा सिस्टम संसाधनों (कांटे) को प्राप्त करने का प्रयास करते हैं। नतीजतन, किसी भी प्रक्रिया को निष्पादित करने का मौका नहीं मिलता क्योंकि वे किसी अन्य प्रक्रिया द्वारा रखे गए किसी अन्य संसाधन की प्रतीक्षा कर रहे होते हैं।
दौर कि शर्ते
रेस कंडीशन एक प्रोग्राम की अवांछित स्थिति है जो तब उत्पन्न होती है जब कोई सिस्टम एक साथ दो या दो से अधिक ऑपरेशन करता है। उदाहरण के लिए, इस साधारण फॉर लूप पर विचार करें:
i=0; # a global variable for x in range(100): print(i) i+=1;
यदि आप बनाते हैं n एक ही समय में इस कोड को चलाने वाले थ्रेड्स की संख्या के आधार पर, प्रोग्राम के निष्पादन समाप्त होने पर i का मान (जो सभी थ्रेड्स द्वारा साझा किया जाता है) निर्धारित नहीं किया जा सकता है। इसका कारण यह है कि वास्तविक मल्टीथ्रेडिंग वातावरण में, थ्रेड्स ओवरलैप हो सकते हैं, और किसी थ्रेड द्वारा प्राप्त और संशोधित i का मान, किसी अन्य थ्रेड द्वारा एक्सेस किए जाने के दौरान बदल सकता है।
ये दो मुख्य प्रकार की समस्याएं हैं जो मल्टीथ्रेडेड या डिस्ट्रीब्यूटेड सिस्टम में उत्पन्न हो सकती हैं। Python अगले भाग में, आप थ्रेड्स को सिंक्रोनाइज़ करके इस समस्या को दूर करना सीखेंगे।
Syncह्रोनाइज़िंग धागे
रेस कंडीशन, डेडलॉक और अन्य थ्रेड-आधारित समस्याओं से निपटने के लिए, थ्रेडिंग मॉड्यूल प्रदान करता है ताला ऑब्जेक्ट। विचार यह है कि जब कोई थ्रेड किसी विशिष्ट संसाधन तक पहुँचना चाहता है, तो वह उस संसाधन के लिए लॉक प्राप्त करता है। एक बार जब कोई थ्रेड किसी विशेष संसाधन को लॉक कर देता है, तो कोई अन्य थ्रेड तब तक उस तक पहुँच नहीं सकता जब तक कि लॉक रिलीज़ न हो जाए। परिणामस्वरूप, संसाधन में परिवर्तन परमाणु होंगे, और रेस की स्थिति टल जाएगी।
लॉक एक निम्न-स्तरीय सिंक्रोनाइजेशन प्रिमिटिव है जिसे द्वारा कार्यान्वित किया जाता है _धागा मॉड्यूल। किसी भी समय, एक लॉक दो अवस्थाओं में से किसी एक में हो सकता है: बंद or खुला हुआ। यह दो विधियों का समर्थन करता है:
- अधिग्रहण करना(): जब लॉक स्थिति अनलॉक हो जाती है, तो acquire() विधि को कॉल करने से स्थिति लॉक हो जाएगी और रिटर्न हो जाएगा। हालांकि, यदि स्थिति लॉक है, तो acquire() को कॉल करना तब तक अवरुद्ध रहेगा जब तक कि किसी अन्य थ्रेड द्वारा release() विधि को कॉल नहीं किया जाता।
- मुक्त करना(): रिलीज़() विधि का उपयोग स्टेट को अनलॉक करने के लिए किया जाता है, यानी लॉक को रिलीज़ करने के लिए। इसे किसी भी थ्रेड द्वारा कॉल किया जा सकता है, ज़रूरी नहीं कि वह थ्रेड ही हो जिसने लॉक हासिल किया हो।
यहां आपके ऐप्स में लॉक का उपयोग करने का एक उदाहरण दिया गया है। अपना ऐप खोलें। IDLE और निम्नलिखित टाइप करें:
import threading lock = threading.Lock() def first_function(): for i in range(5): lock.acquire() print ('lock acquired') print ('Executing the first funcion') lock.release() def second_function(): for i in range(5): lock.acquire() print ('lock acquired') print ('Executing the second funcion') lock.release() if __name__=="__main__": thread_one = threading.Thread(target=first_function) thread_two = threading.Thread(target=second_function) thread_one.start() thread_two.start() thread_one.join() thread_two.join()
अब, F5 दबाएँ। आपको कुछ इस तरह का आउटपुट दिखाई देगा:
कोड स्पष्टीकरण
- यहाँ, आप बस कॉल करके एक नया लॉक बना रहे हैं थ्रेडिंग.लॉक() फैक्ट्री फ़ंक्शन। आंतरिक रूप से, लॉक() प्लेटफ़ॉर्म द्वारा बनाए रखा गया सबसे प्रभावी कंक्रीट लॉक क्लास का एक उदाहरण देता है।
- पहले कथन में, आप acquire() विधि को कॉल करके लॉक प्राप्त करते हैं। जब लॉक प्रदान किया जाता है, तो आप प्रिंट करते हैं “लॉक अधिग्रहित” कंसोल पर। एक बार जब आप थ्रेड को चलाने के लिए जो कोड चाहते हैं उसका निष्पादन समाप्त हो जाता है, तो आप रिलीज़() विधि को कॉल करके लॉक को रिलीज़ करते हैं।
सिद्धांत तो ठीक है, लेकिन आपको कैसे पता चलेगा कि लॉक ने सही ढंग से काम किया? आउटपुट देखने पर आपको पता चलेगा कि प्रत्येक प्रिंट स्टेटमेंट एक बार में एक ही लाइन प्रिंट कर रहा है। याद कीजिए, पिछले उदाहरण में, प्रिंट का आउटपुट अनियमित था क्योंकि कई थ्रेड एक ही समय में प्रिंट() मेथड का उपयोग कर रहे थे। यहाँ, प्रिंट फ़ंक्शन को लॉक प्राप्त होने के बाद ही कॉल किया जाता है। इसलिए, आउटपुट एक-एक करके और लाइन दर लाइन प्रदर्शित होता है।
ताले के अलावा, Python यह थ्रेड सिंक्रोनाइज़ेशन को संभालने के लिए कुछ अन्य तंत्रों का भी समर्थन करता है, जैसा कि नीचे सूचीबद्ध है:
- आरलॉक्स
- Semaphores
- स्थितियां
- घटनाएँ, और
- बाधाओं
ग्लोबल इंटरप्रेटर लॉक (और इससे कैसे निपटें)
विवरण में जाने से पहले Pythonजीआईएल के उपलक्ष्य में, आइए कुछ ऐसे शब्दों को परिभाषित करें जो आगामी अनुभाग को समझने में उपयोगी होंगे:
- सीपीयू-बाउंड कोड: इससे तात्पर्य कोड के किसी भी ऐसे भाग से है जिसे सीधे सीपीयू द्वारा निष्पादित किया जाएगा।
- इनपुट/आउटपुट-बाउंड कोड: यह कोई भी ऐसा कोड हो सकता है जो ऑपरेटिंग सिस्टम के माध्यम से फाइल सिस्टम तक पहुंचता है।
- CPython: यह संदर्भ है कार्यान्वयन of Python और इसे C और C में लिखे गए इंटरप्रेटर के रूप में वर्णित किया जा सकता है Python (प्रोग्रामिंग भाषा)
GIL क्या है? Python?
ग्लोबल इंटरप्रेटर लॉक (GIL) in Python GIL एक प्रोसेस लॉक या म्यूटेक्स है जिसका उपयोग प्रोसेस को मैनेज करते समय किया जाता है। यह सुनिश्चित करता है कि एक समय में केवल एक ही थ्रेड किसी विशेष रिसोर्स को एक्सेस कर सके, और यह ऑब्जेक्ट्स और बाइटकोड के एक साथ उपयोग को भी रोकता है। इससे सिंगल-थ्रेडेड प्रोग्राम्स के परफॉर्मेंस में सुधार होता है। Python यह बहुत ही सरल और लागू करने में आसान है।
लॉक का उपयोग यह सुनिश्चित करने के लिए किया जा सकता है कि किसी निश्चित समय पर केवल एक थ्रेड को ही किसी विशेष संसाधन तक पहुंच प्राप्त हो।
की विशेषताओं में से एक है Python इसका मतलब यह है कि यह प्रत्येक इंटरप्रेटर प्रक्रिया पर एक वैश्विक लॉक का उपयोग करता है, जिसका अर्थ है कि प्रत्येक प्रक्रिया इसे अलग तरह से मानती है। Python दुभाषिया स्वयं एक संसाधन के रूप में।
उदाहरण के लिए, मान लीजिए कि आपने लिखा है Python यह प्रोग्राम दो थ्रेड्स का उपयोग करके CPU और इनपुट/आउटपुट दोनों ऑपरेशन करता है। इस प्रोग्राम को चलाने पर ये परिणाम मिलते हैं:
- RSI Python इंटरप्रेटर एक नई प्रक्रिया बनाता है और थ्रेड्स को उत्पन्न करता है।
- जब थ्रेड-1 चलना शुरू करता है, तो वह सबसे पहले GIL प्राप्त करेगा और उसे लॉक करेगा।
- यदि थ्रेड-2 अभी निष्पादित करना चाहता है, तो उसे GIL के जारी होने की प्रतीक्षा करनी होगी, भले ही कोई अन्य प्रोसेसर मुक्त हो।
- अब, मान लीजिए कि थ्रेड-1 I/O ऑपरेशन का इंतज़ार कर रहा है। इस समय, यह GIL जारी करेगा, और थ्रेड-2 इसे प्राप्त करेगा।
- I/O ऑप्स पूरा करने के बाद, यदि थ्रेड-1 अब निष्पादित करना चाहता है, तो उसे फिर से थ्रेड-2 द्वारा GIL जारी किए जाने की प्रतीक्षा करनी होगी।
इस कारणवश, एक समय में केवल एक ही थ्रेड इंटरप्रेटर तक पहुंच सकता है, जिसका अर्थ है कि केवल एक ही थ्रेड एक्जीक्यूट होगा। Python किसी निश्चित समय पर कोड।
सिंगल-कोर प्रोसेसर में यह ठीक है क्योंकि इसमें थ्रेड्स को संभालने के लिए टाइम स्लाइसिंग (इस ट्यूटोरियल के पहले भाग को देखें) का उपयोग किया जाता है। हालांकि, मल्टी-कोर प्रोसेसर के मामले में, कई थ्रेड्स पर चलने वाला CPU-बाउंड फ़ंक्शन प्रोग्राम की दक्षता पर काफी प्रभाव डालेगा क्योंकि यह वास्तव में एक ही समय में सभी उपलब्ध कोर का उपयोग नहीं कर रहा होगा।
जी.आई.एल. की आवश्यकता क्यों पड़ी?
सीPython गार्बेज कलेक्टर रेफरेंस काउंटिंग नामक एक कुशल मेमोरी प्रबंधन तकनीक का उपयोग करता है। यह इस प्रकार काम करता है: प्रत्येक ऑब्जेक्ट Python ऑब्जेक्ट का एक रेफरेंस काउंट होता है, जो तब बढ़ता है जब इसे किसी नए वेरिएबल को नाम दिया जाता है या किसी कंटेनर (जैसे टपल, लिस्ट आदि) में जोड़ा जाता है। इसी तरह, रेफरेंस काउंट तब घटता है जब रेफरेंस स्कोप से बाहर हो जाता है या जब del स्टेटमेंट को कॉल किया जाता है। जब किसी ऑब्जेक्ट का रेफरेंस काउंट 0 हो जाता है, तो उसे गार्बेज कलेक्ट कर लिया जाता है और आवंटित मेमोरी मुक्त हो जाती है।
लेकिन समस्या यह है कि रेफरेंस काउंट वेरिएबल किसी भी अन्य ग्लोबल वेरिएबल की तरह रेस कंडीशन से ग्रस्त हो सकता है। इस समस्या को हल करने के लिए, डेवलपर्स ने Python हमने ग्लोबल इंटरप्रेटर लॉक का उपयोग करने का निर्णय लिया। दूसरा विकल्प प्रत्येक ऑब्जेक्ट में एक लॉक जोड़ना था, जिसके परिणामस्वरूप डेडलॉक की स्थिति उत्पन्न होती और acquire() और release() कॉल से ओवरहेड बढ़ जाता।
इसलिए, मल्टीथ्रेडेड के लिए जीआईएल एक महत्वपूर्ण प्रतिबंध है। Python ऐसे प्रोग्राम जो भारी CPU-आधारित ऑपरेशन चलाते हैं (प्रभावी रूप से उन्हें सिंगल-थ्रेडेड बनाते हैं)। यदि आप अपने एप्लिकेशन में कई CPU कोर का उपयोग करना चाहते हैं, तो इसका उपयोग करें। बहु इसके बजाय मॉड्यूल।








