目次

1. Python का थ्रेड भनेको के हो?

Python का थ्रेडहरू प्रोग्रामभित्र एउटै समयमा धेरै टास्कहरू चलाउनका लागि भएको संयन्त्र हुन्। थ्रेड प्रयोग गर्दा, प्रोग्रामका केही भागहरू अन्य भागको प्रतीक्षा नगरी समानान्तर रूपमा चल्ने भएकाले, प्रोसेसिङलाई कुशलतापूर्वक अघि बढाउन सम्भव हुन्छ। Python मा, threading मोड्युल प्रयोग गरेर थ्रेडहरू सिर्जना र व्यवस्थापन गर्न सकिन्छ।

थ्रेडको आधारभूत अवधारणा

थ्रेड भनेको प्रोसेस भित्र चल्ने हल्का कार्यान्वयन एकाइ हो। एउटै प्रोसेसभित्र धेरै थ्रेडहरू चल्न सक्छन्, र तिनीहरूले स्वतन्त्र रूपमा काम गर्ने भएकाले, प्रोग्रामको समानान्तर प्रोसेसिङ सम्भव हुन्छ। विशेषगरी I/O अपरेशनहरू (फाइल पढ्ने-लेख्ने वा नेटवर्क सञ्चार) र युजर इन्टरफेसको प्रतिक्रिया सुधारमा उपयोगी हुन्छ।

Python मा थ्रेडको प्रयोगका उदाहरणहरू

उदाहरणका लागि, वेब स्क्र्यापिङ टुल बनाउँदा, धेरै वेब पेजहरूमा समानान्तर रूपमा पहुँच गरेर, समग्र प्रोसेसिङ समय घटाउन सकिन्छ। साथै, रियल-टाइममा डेटा प्रोसेसिङ गर्ने एप्लिकेसनहरूमा, मुख्य प्रोसेस रोकिनु नदिई ब्याकग्राउन्डमा डेटाको अद्यावधिक गर्न सकिन्छ।

2. Python मा Global Interpreter Lock(GIL) को बुझाइ

Python का थ्रेडहरूको सन्दर्भमा, Global Interpreter Lock(GIL) अत्यन्तै महत्वपूर्ण अवधारणा हो। GIL भनेको Python इन्टरप्रेटरले एकै पटक एक मात्र थ्रेड चलाउन सक्ने गरी प्रतिबन्ध लगाउने संयन्त्र हो।

GIL को प्रभाव

GIL ले थ्रेडहरू एकै साथ चल्न नदिई, एउटै प्रोसेस भित्रको मेमोरी व्यवस्थापनको एकरूपता जोगाउँछ। तर, यस प्रतिबन्धका कारण, CPU-बाउन्ड कामहरू(CPU लाई धेरै प्रयोग गर्ने प्रक्रिया)मा थ्रेडद्वारा हुने समानान्तर प्रसंस्करणका फाइदा सीमित हुन्छन्। उदाहरणका लागि, धेरै थ्रेडहरूमा जटिल गणना गरे पनि, GIL का कारण एउटै समयमा एक मात्र थ्रेड चल्ने भएकाले, अपेक्षित कार्यसम्पादन सुधार हासिल हुँदैन।

GIL लाई परिहार गर्ने उपाय

GIL का प्रतिबन्धहरूलाई परिहार गर्न, multiprocessing मोड्युल प्रयोग गरेर प्रोसेसहरूलाई समानान्तर बनाउने विधि प्रभावकारी हुन्छ। multiprocessing मा, प्रत्येक प्रोसेससँग स्वतन्त्र Python इन्टरप्रेटर हुन्छ, त्यसैले GIL को प्रभाव नपरी समानान्तर प्रसंस्करण सम्भव हुन्छ।

3. Python को threading मोड्युलको आधारभूत प्रयोग गर्ने तरिका

threading मोड्युल Python मा थ्रेड बनाउन र चलाउनका लागि मानक लाइब्रेरी हो। यहाँ, यसको आधारभूत प्रयोगबारे व्याख्या गर्छौं।

थ्रेडको सिर्जना र कार्यान्वयन

थ्रेड बनाउन threading.Thread कक्षा प्रयोग गरिन्छ। उदाहरणका लागि, तल देखिएझैं थ्रेड सिर्जना गरेर चलाउन सकिन्छ।
import threading
import time

def my_function():
    time.sleep(2)
    print("Thread executed")

# थ्रेडको सिर्जना
thread = threading.Thread(target=my_function)

# थ्रेड सुरु
thread.start()

# थ्रेड समाप्त हुन प्रतीक्षा गर्ने
thread.join()
print("Main thread completed")
यस कोडमा, नयाँ थ्रेड सिर्जना हुन्छ र my_function असमकालिक रूपमा चलाइन्छ।

थ्रेडको समक्रमण

थ्रेडको समाप्ति पर्खनका लागि, join() मेथड प्रयोग गरिन्छ। यो मेथडले थ्रेड समाप्त नहुँदासम्म मुख्य थ्रेडको कार्यान्वयन रोक्ने भएकाले, थ्रेडहरूबीच समक्रमण सम्भव हुन्छ।

4. Thread क्लासलाई सबक्लास बनाएर थ्रेड सिर्जना गर्ने

threading.Thread क्लासलाई सबक्लास बनाएर, थ्रेडहरूलाई अझ लचिलो रूपमा अनुकूलित गर्न सकिन्छ।
年収訴求

Thread को सबक्लासिङ

तल देखिएझैं, Thread क्लासलाई सबक्लास गरेर आफ्नै थ्रेड क्लास बनाइन्छ, र run() मेथडलाई ओभरराइड गरिन्छ।
import threading
import time

class MyThread(threading.Thread):
    def run(self):
        time.sleep(2)
        print("Custom thread executed")

# कस्टम थ्रेड बनाउने र चलाउने
thread = MyThread()
thread.start()
thread.join()
print("Main thread completed")

सबक्लासिङका फाइदा

सबक्लासिङमार्फत, थ्रेडले गर्ने कामलाई क्याप्सुलेट गर्न र पुनः प्रयोग गर्न सजिलो हुने कोड लेख्न सकिन्छ। साथै, प्रत्येक थ्रेडमा फरक डाटा राख्ने जस्ता, लचिलो थ्रेड व्यवस्थापन सम्भव हुन्छ।

5. थ्रेडको सुरक्षितता र समक्रमण

धेरै थ्रेडहरूले एउटै रिसोर्समा पहुँच गर्दा, डेटाको अखण्डता जोगाउन समक्रमण आवश्यक हुन्छ।

रेस कन्डिसन

रेस कन्डिसन भनेको धेरै थ्रेडहरूले एकै समयमा एउटै रिसोर्स परिवर्तन गर्दा अनपेक्षित परिणाम उत्पन्न हुने अवस्था हो। उदाहरणका लागि, काउन्टर भेरिएबललाई धेरै थ्रेडहरूले बढाउने क्रममा, उचित समक्रमण नभएमा, सही नतिजा प्राप्त नहुन सक्छ।

लकद्वारा समक्रमण

threading मोड्युलमा, थ्रेडहरूको समक्रमण गर्नका लागि Lock अब्जेक्ट उपलब्ध छ। Lock प्रयोग गर्दा, एउटा थ्रेडले रिसोर्स प्रयोग गरिरहँदा, अन्य थ्रेडहरूले सो रिसोर्समा पहुँच गर्नबाट रोक्न सकिन्छ।
import threading

counter = 0
lock = threading.Lock()

def increment_counter():
    global counter
    with lock:
        counter += 1

threads = []
for _ in range(100):
    thread = threading.Thread(target=increment_counter)
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

print("Final counter value:", counter)
यस उदाहरणमा, with lock ब्लक भित्र मात्रै काउन्टर बढाइने भएकाले, डेटाको अखण्डता जोगाइन्छ।

6. थ्रेड र I/O-बाउन्ड बनाम CPU-बाउन्ड कार्यहरू

थ्रेडहरू I/O-बाउन्ड कार्यहरू (फाइल सञ्चालन, सञ्जाल सञ्चार आदि) मा विशेष रूपमा प्रभावकारी हुन्छन्।

I/O-बाउन्ड कार्यहरूमा थ्रेडहरूको लाभ

I/O-बाउन्ड कार्यहरूले प्रक्रियाको क्रममा धेरै समय प्रतीक्षामा बिताउने भएकाले, थ्रेड प्रयोग गरेर अन्य कार्यहरूलाई समानान्तर रूपमा चलाउँदा, प्रोग्रामको समग्र दक्षता सुधार गर्न सकिन्छ। उदाहरणका लागि, फाइल पढ्ने/लेख्ने काम गर्ने थ्रेड र सञ्जाल सञ्चार गर्ने थ्रेडलाई समानान्तर रूपमा चलाउँदा, प्रतीक्षा समय घटाउन सकिन्छ।

CPU-बाउन्ड कार्यहरू रmultiprocessing

CPU-बाउन्ड कार्यहरू (संख्यात्मक गणना, डाटा प्रशोधन आदि) का लागि threading होइन, multiprocessing मोड्युल प्रयोग गर्न सिफारिस गरिन्छ। multiprocessing GIL को प्रभावबाट प्रभावित नहुने भएकाले, मल्टिकोर प्रोसेसरको सदुपयोग गरेर प्रदर्शन सुधार गर्न सकिन्छ।

7. थ्रेडको व्यवस्थापन

Python का थ्रेडहरूलाई दक्षतापूर्वक व्यवस्थापन गर्नका लागि प्रविधिहरूबारे व्याख्या गर्छौँ।

थ्रेडको नामकरण र पहिचान

थ्रेडमा नाम दिने हो भने, डिबगिङ वा लग आउटपुटको समयमा थ्रेडलाई सजिलै पहिचान गर्न सकिन्छ。threading.Thread को name आर्गुमेन्टमार्फत थ्रेडको नाम तोक्न सकिन्छ।
import threading

def task():
    print(f"Thread {threading.current_thread().name} is running")

thread1 = threading.Thread(target=task, name="Thread1")
thread2 = threading.Thread(target=task, name="Thread2")

thread1.start()
thread2.start()

थ्रेडको स्थिति जाँच

थ्रेड हाल चलिरहेको छ कि छैन भनेर पुष्टि गर्न is_alive() मेथड प्रयोग गरिन्छ। यो मेथडले, थ्रेड चलिरहेको भए True र समाप्त भइसकेको भए False फर्काउँछ। थ्रेडको स्थितिलाई उचित रूपमा व्यवस्थापन गर्दा, प्रोग्रामको अप्रत्याशित व्यवहार रोक्न सकिन्छ।
import threading
import time

def task():
    time.sleep(1)
    print("Task completed")

thread = threading.Thread(target=task)
thread.start()

# थ्रेड चलिरहेको छ कि छैन भनेर जाँच
if thread.is_alive():
    print("Thread is still running")
else:
    print("Thread has finished")

थ्रेड बन्द गर्ने

Python को threading मोड्युलमा थ्रेडलाई प्रत्यक्ष रूपमा रोक्ने उपाय छैन। यसको कारण, थ्रेडलाई जबरजस्ती बन्द गर्दा डाटाको असङ्गति वा स्रोतहरू मुक्त नहुनु (लीक) जस्ता समस्याहरू हुन सक्छन्। थ्रेडलाई सुरक्षित रूपमा रोक्न, थ्रेड चलिरहेको लूपमा फ्ल्याग राखेर समाप्ति नियन्त्रण गर्ने तरिका प्रचलित छ।
import threading
import time

stop_thread = False

def task():
    while not stop_thread:
        print("Thread is running")
        time.sleep(1)

thread = threading.Thread(target=task)
thread.start()

time.sleep(5)
stop_thread = True
thread.join()
print("Thread has been stopped")

8. थ्रेड रmultiprocessing को तुलना

थ्रेड र प्रोसेसका फरक बुझ्नु र प्रत्येकको उपयुक्त प्रयोग क्षेत्र थाहा हुनु महत्त्वपूर्ण छ।

थ्रेडका लाभ र कमजोरीहरू

थ्रेड हलुका हुन्छन्, उही प्रोसेसभित्र मेमोरी साझा गर्न सकिने भएकाले ओभरहेड कम हुन्छ र I/O-बाउन्ड टास्कका लागि उपयुक्त हुन्छन्। तर, अघि उल्लेख गरेअनुसार, Python को GIL का कारण CPU-बाउन्ड टास्कको प्रदर्शन सीमित हुन सक्छ।

multiprocessing मोड्युलका लाभ

multiprocessing मोड्युलमा प्रत्येक प्रोसेसले स्वतन्त्र Python इन्टरप्रिटर राख्ने भएकाले, GIL को प्रभावबाट मुक्त रहँदै CPU कोरहरूलाई अधिकतम रूपमा प्रयोग गर्न सकिन्छ। यो CPU-बाउन्ड टास्कमा ठूलो फाइदा हुन्छ। तर, प्रोसेसहरूबीच डाटालाई साझा गर्न पाइप वा क्यू प्रयोग गर्नुपर्ने हुन्छ र थ्रेडको तुलनामा ओभरहेड ठूलो हुन्छ।

छनोटका मुख्य बुँदाहरू

  • थ्रेड प्रयोग गर्ने बेला: I/O-बाउन्ड टास्क, GUI अनुप्रयोगको प्रतिक्रियाशीलता सुधार जस्ता, GIL को प्रभाव कम पर्ने स्थितिहरू।
  • multiprocessing प्रयोग गर्ने बेला: CPU-बाउन्ड टास्क, उन्नत समानान्तर प्रसंस्करण आवश्यक हुने आदि, GIL का प्रतिबन्धबाट जोगिन चाहिने स्थितिहरू।

9. Python को threading मोड्युलका सर्वोत्तम अभ्यासहरू

मल्टि-थ्रेडिङ प्रोग्रामिङमा केही सर्वोत्तम अभ्यासहरू पालना गरेर, स्थिर सञ्चालन र डिबगिङको सहजता सुनिश्चित गर्न सकिन्छ。

थ्रेडको सुरक्षित अन्त्य

थ्रेडको जबरजस्ती अन्त्य नगर्नुहोस्; फ्ल्याग वा कन्डिसन भेरिएबल प्रयोग गरेर थ्रेड सुरक्षित रूपमा अन्त्य हुने व्यवस्था गर्नुहोस्। साथै, थ्रेडले स्रोत प्रयोग गरिरहेको भए अवश्यै ती स्रोतहरू मुक्त गर्ने कोड कार्यान्वयन गर्नुहोस्。

डेडलक रोक्नुहोस्

लक प्रयोग गरेर थ्रेडको सिंक्रोनाइजेसन गर्दा, डेडलक रोक्न निम्न बुँदाहरूमा ध्यान दिनुहोस्।
  • लक प्राप्त गर्ने क्रम तय गरेर एकरूपता कायम राख्नुहोस्।
  • आवश्यक न्यूनतम दायरामा मात्र लक प्राप्त गर्नुहोस्।
  • सम्भव भए with स्टेटमेन्ट प्रयोग गरेर लक रिलिजलाई स्वचालित बनाउनुहोस्।

डिबगिङ र लग

थ्रेड प्रयोग गरिएका प्रोग्रामहरूमा डिबगिङ कठिन हुन सक्छ। त्यसैले, लगको उपयोग गरेर थ्रेडको व्यवहार ट्र्याक गर्न सक्ने बनाउनुहोस्। logging मोड्युल प्रयोग गरेर थ्रेड-प्रति लग रेकर्ड गर्दा, समस्याको पहिचान सजिलो हुन्छ।
import threading
import logging

logging.basicConfig(level=logging.DEBUG, format='%(threadName)s: %(message)s')

def task():
    logging.debug('Starting')
    logging.debug('Exiting')

thread = threading.Thread(target=task, name='MyThread')
thread.start()

10. सारांश

Python को threading मोड्युल कार्यक्रमको सहवर्ती प्रसंस्करण कार्यान्वयन गर्नका लागि शक्तिशाली उपकरण हो। यस लेखमा, थ्रेडको आधारभूत प्रयोगदेखि, GIL को प्रभाव, थ्रेड र multiprocessing लाई कहिले कसरी छुट्याएर प्रयोग गर्ने, र थ्रेड प्रयोग गर्दा अपनाउनुपर्ने सर्वोत्तम अभ्यासहरूसम्म व्यापक रूपमा समेटिएको छ। थ्रेडहरू I/O-बाउन्ड कार्यहरूको दक्षता बढाउन उपयुक्त हुन्छन्, तर GIL को अस्तित्वलाई बुझेर, अवस्थाअनुसार उचित रूपमा छुट्याएर प्रयोग गर्नु महत्त्वपूर्ण छ। थ्रेडको व्यवस्थापन र सुरक्षामा ध्यान दिएर, सबैभन्दा उपयुक्त प्रोग्रामिङ विधि छनोट गर्दा, Python कार्यक्रमको प्रदर्शन र विश्वसनीयता सुधार गर्न सकिन्छ। आगामी दिनमा अझ उन्नत थ्रेड प्रशोधन वा सहवर्ती प्रोग्रामिङमा चुनौती लिन चाहनुहुन्छ भने, आधिकारिक दस्तावेज र विशेषज्ञ पुस्तकहरू सन्दर्भ गरेर, अझ गहिरो बुझाइ हासिल गर्न प्रयास गर्नुहोस्。
年収訴求