آموزش ماژول threading – کلاس Semaphore و BoundedSemaphore

Please login to bookmark Close

پیش‌نیاز ها

برای درک بهتر از مطالب این بخش، لازم است با مفاهیم قفل گذاری در مولتی تردینگ آشنا باشید.

کلاس Semaphore

با استفاده از کلاس Semaphore می‌توان تعداد حداکثر ترد هایی که در یک لحظه می‌توانند به صورت مشترک به منابع اشتراکی دسترسی داشته باشند را مشخص کرد.

تعداد ترد هایی که همزمان می‌توانند به منبع اشتراکی دسترسی داشته باشند با یک شمارنده مدیریت می‌شود. فراخوانی acquire یک واحد از آن کم و فراخوانی release یک واحد به آن اضافه می‌کند. به عبارت دیگر:

  • ابتدا یک قفل ساخته می‌شود.
  • هر بار که acquire فراخوانی شود یکی از آن شمارنده کم می‌شود.
  • هر بار که release فراخوانی شود یکی به آن شمارنده اضافه می‌شود.

فرض کنید بخواهیم در هر لحظه حداکثر دو ترد به صورت همزمان بتوانند به منابع مشترک دسترسی داشته باشند. بدین منظور باید کلاس Semaphore را به شکل زیر به کار بگیریم.

from time import sleep
from threading import Thread, Semaphore, current_thread

num = 0
lock = Semaphore(2)

def add():
    lock.acquire()
    # Access to common resources
    print('Downloading image by', current_thread().name)
    sleep(1)
    lock.release()

t1 = Thread(target=add)
t2 = Thread(target=add)
t3 = Thread(target=add)
t4 = Thread(target=add)
t5 = Thread(target=add)

t1.start()
t2.start()
t3.start()
t4.start()
t5.start()

مشکل عملکرد Semaphore

برنامه هایی که در دنیای واقعی نوشته می‌شوند همیشه به سادگی مثال های دوره های آموزشی نیست. گاهی ممکن است کد ها پیچیده شوند و ناخواسته الگوریتم برنامه به نحوی باشد که تعداد فراخوانی های release بیشتر از acquire باشد. در اینصورت عملکرد Semaphore خراب می‌شود.

مثلا در کد زیر، به ازای هر بار acquire دو بار release فراخوانی می‌شود.

from time import sleep
from threading import Thread, Semaphore, current_thread

num = 0
lock = Semaphore(2)

def add():
    lock.acquire()
    print('Downloading image by', current_thread().name)
    sleep(2)
    lock.release()
    lock.release()

threads = []
for i in range(13):
    threads.append(Thread(target=add))

for t in threads:
    t.start()

مشکل کد بالا این است که به مرور زمان، تعداد ترد هایی که به صورت همزمان به منابع مشترک دسترسی پیدا می‌کنند به مرور بیشتر می‌شود.

کلاس BoundedSemaphore

برای جلوگیری از مشکلی که برای کلاس Semaphore مطرح شد، می‌توان از کلاس BoundedSemaphore استفاده کرد.

هر بار که release بیش از اندازه فراخوانی شود، یک ValueError رخ می‌دهد.

from time import sleep
from threading import Thread, BoundedSemaphore, current_thread

num = 0
lock = BoundedSemaphore(2)

def add():
    try:
        lock.acquire()
        print('Downloading image by', current_thread().name)
        sleep(2)
        lock.release()
        lock.release()
    except ValueError:
        print('Can not release', current_thread().name)


threads = []
for i in range(13):
    threads.append(Thread(target=add))

for t in threads:
    t.start()

مقایسه Semaphore و BoundedSemaphore

از آنجایی که BoundedSemaphore علاوه بر داشتن امکانات Semaphore، مشکلات آن را هم ندارد، احتمالا این سوال به ذهن شما خطور کرده باشد که استفاده از Semaphore در چه مواردی می‌تواند کاربرد داشته باشد؟

کلاس BoundedSemaphore پس از Semaphore توسعه یافته است. به همین دلیل ممکن است برخی کد های قدیمی وجود داشته باشد که با Semaphore توسعه یافته باشند. نگه داشتن Semaphore تنها کمکی که می‌کند این است که آن کد های قدیمی، کمتر نیاز به ریفکتور و هماهنگی با نسخه های جدید پایتون داشته باشند. پس می‌توان گفت، تنها دلیل حذف نشدن Semaphore در واقع Backward Compatibility است.

خلاصه

همیشه برای ایجاد محدودیت تعداد ترد ها از BoundedSemaphore استفاده کنید.

Please login to bookmark Close
پیشرفت شما در «دوره آموزش کانکارنسی در پایتون» (29%)
نظرات

دیدگاهتان را بنویسید

29%
پیشرفت
فهرست مطالب

تمرین

این قسمت تمرین ندارد!

پاسخ تمرین ها

هنوز برای تمرین‌های این قسمت پاسخی ثبت نشده است!

اشتراک گذاری

چرا بهتره از فیلترشکن استفاده کنید؟

من همه ویدئو ها و پادکست های کُدباز رو توی یوتیوب و ساندکلود و پلتفرم هایی آپلود می‌کنم که اغلب فیلتر هستند.

اغلب آموزش‌ها ویدئو و پادکست دارند. پس اگر می‌خواهید از محتوای سایت بیشترین استفاده رو ببرید نیاز به فیلتر شکن دارید.

توجه داشته باشید که برای خرید از فروشگاه بهتره فیلتر شکن رو خاموش کنید.

تنظیمات

انتخاب زبان
تغییر تم