چندریسمانی (Multithreading) در پایتون
چندریسمانی (Multithreading) یکی از مفاهیم کلیدی در برنامهنویسی است که به ما اجازه میدهد تا چندین رشته (Thread) را همزمان اجرا کنیم. در پایتون، چندریسمانی به طور خاص برای بهبود عملکرد برنامههای I/O-Heavy مورد استفاده قرار میگیرد، مانند برنامههای شبکهای یا دسترسی به فایل. این روش به ما اجازه میدهد تا فرآیندهای متعدد را همزمان مدیریت کنیم بدون نیاز به اجرای جداگانه آنها.
چرا چندریسمانی در پایتون مهم است؟
در زمانی که یک برنامه منتظر دادههای ورودی یا خروجی است (مثل اتصال به دیتابیس، فایل یا API)، چندریسمانی میتواند بقیه رشتهها را بدون توقف کار کنند. این امر منجر به بهبود سرعت و بهرهوری برنامه میشود.
چه چیزی در پایتون چندریسمانی را امکانپذیر میکند؟
پایتون از کتابخانه `threading` برای مدیریت چند رشته فراهم میکند. این کتابخانه به ما اجازه میدهد تا رشتهها را ایجاد، مدیریت و متصل کنیم.
import threading
import time
def print_numbers():
for i in range(5):
print(i)
time.sleep(1)
# ایجاد یک رشته جدید
thread = threading.Thread(target=print_numbers)
thread.start()
thread.join() # منتظر ماندن تا اتمام رشته
در این کد، ما یک رشته جدید با استفاده از `threading.Thread` ایجاد کردهایم. این رشته تابع `print_numbers` را اجرا میکند. با استفاده از `start()`، رشته شروع به اجرا میشود و با `join()` منتظر ماندن تا پایان اجرای آن میشویم.
روشهای چندریسمانی در پایتون
- استفاده از کلاس Thread: برای ایجاد رشتههای ساده و کاربردی.
- استفاده از ThreadPoolExecutor: برای مدیریت بهتر رشتهها در برنامههای پیچیدهتر.
کلاس Thread در پایتون
برای ایجاد یک رشته، میتوانیم از کلاس `Thread` استفاده کنیم. در اینجا یک مثال ساده آورده شده است:
import threading
import time
def worker(name):
for i in range(3):
print(f"Worker {name} is working on task {i}")
time.sleep(1)
# ایجاد دو رشته
t1 = threading.Thread(target=worker, args=("A",))
t2 = threading.Thread(target=worker, args=("B",))
# شروع رشتهها
t1.start()
t2.start()
# انتظار تا پایان اجرای رشتهها
t1.join()
t2.join()
در این کد، دو رشته از نوع `worker` ایجاد شدهاند. هر کدام یک اسم متفاوت به عنوان ورودی دریافت میکنند. با استفاده از `start()`، اجرا شروع میشود و با `join()` منتظر ماندن تا پایان.
استفاده از ThreadPoolExecutor
برای مدیریت چندین رشته به صورت کارآمدتر، میتوان از `ThreadPoolExecutor` استفاده کرد. این کلاس از کتابخانه `concurrent.futures` فراهم شده است:
from concurrent.futures import ThreadPoolExecutor
import time
def task(name):
print(f"Task {name} started")
time.sleep(2)
print(f"Task {name} completed")
# ایجاد چندین کار در یک Executor
with ThreadPoolExecutor(max_workers=3) as executor:
futures = [executor.submit(task, i) for i in range(5)]
# منتظر ماندن تا تمام کارها انجام شوند
for future in futures:
future.result()
در این مثال، 5 کار به صورت همزمان با استفاده از `ThreadPoolExecutor` اجرا شدهاند. تعداد حداکثر رشتههای فعال در هر لحظه برابر 3 است. این روش برای مدیریت کارهای متعدد و پیچیده مناسب است.
مزایا و معایب چندریسمانی در پایتون
| مزایا | معایب |
|---|---|
| • بهبود سرعت در برنامههای I/O-Heavy | • مشکلات مربوط به رقابت بین رشتهها (Race Condition) |
| • استفاده مؤثر از منابع سیستم | • پیچیدگی در مدیریت رشتهها در برنامههای بزرگ |
| • قابلیت اجرای چندین فعالیت همزمان | • محدودیتهای چندریسمانی در پایتون (GIL) |
محدودیت GIL در پایتون
یکی از مهمترین محدودیتهای چندریسمانی در پایتون، GIL (Global Interpreter Lock) است. GIL باعث میشود که فقط یک رشته در هر زمان بتواند کد پایتون را اجرا کند. بنابراین، چندریسمانی برای CPU-Heavy مفید نیست و بهتر است از multiprocessing استفاده شود.
نکات مهم در استفاده از چندریسمانی
- استفاده از `join()` برای جلوگیری از خروج زودهنگام برنامه
- استفاده از قفلها (Locks) برای جلوگیری از رقابت رشتهها
- پایداری در مدیریت رشتهها و تخصیص منابع
استفاده از Lock در چندریسمانی
برای جلوگیری از رقابت بین رشتهها، میتوانیم از `threading.Lock()` استفاده کنیم:
import threading
import time
# متغیر مشترک
counter = 0
lock = threading.Lock()
def increment():
global counter
for _ in range(100000):
with lock:
counter += 1
# ایجاد دو رشته
t1 = threading.Thread(target=increment)
t2 = threading.Thread(target=increment)
t1.start()
t2.start()
t1.join()
t2.join()
print(counter) # باید 200000 باشد
در این کد، دو رشته به طور همزمان روی متغیر `counter` کار میکنند. با استفاده از `lock`، جلوگیری از رقابت بین رشتهها صورت میگیرد و نتیجهای دقیق به دست میآید.
چکیده
چندریسمانی در پایتون ابزار قدرتمندی است برای بهبود عملکرد برنامههای I/O-Heavy. با استفاده از کتابخانه `threading` و `concurrent.futures` میتوانیم رشتههای مختلف را مدیریت کنیم. البته باید به GIL و مشکلات رقابت رشتهها توجه کنیم. در صورت نیاز به اجرای موازی CPU-Heavy، از `multiprocessing` استفاده کنید.
آیا این مطلب برای شما مفید بود ؟




