آموزش ماژول asyncio – کلاس Condition

Please login to bookmark Close

مقدمه

کلاس Event که در درس قبل دیدیم، فقط یک سیگنال ساده مخابره می‌کند و اطلاعی از وضعیت داده‌های مشترک ندارد. اما گاهی یک Task باید منتظر بماند تا یک شرط خاص دربارهٔ داده‌های مشترک برقرار شود؛ مثلاً «منتظر بمان تا صف خالی نباشد». کلاس Condition در asyncio دقیقاً برای این منظور طراحی شده و یک Lock را با قابلیت wait/notify ترکیب می‌کند.

ساخت یک Condition

با فراخوانی asyncio.Condition() یک شیء Condition ساخته می‌شود که به‌صورت داخلی یک asyncio.Lock نیز دارد. تمام عملیات روی داده‌های مشترک باید درون async with condition انجام شود تا از دسترسی هم‌زمان و ناخواسته جلوگیری شود.

متدهای اصلی کلاس Condition

  • await condition.wait(): «باید درون async with صدا زده شود؛ Lock را موقتاً آزاد می‌کند، منتظر notify می‌ماند و سپس دوباره Lock را می‌گیرد.»
  • await condition.wait_for(predicate): «به‌صورت تکرارشونده wait() را صدا می‌زند تا زمانی که تابع predicate مقدار True برگرداند.»
  • condition.notify(n=1): «یک یا چند Task منتظر را بیدار می‌کند (پیش‌فرض فقط یکی).»
  • condition.notify_all(): «همهٔ Task‌های منتظر را بیدار می‌کند.»

مثال: Producer-Consumer با شرط مشخص

در این مثال، Consumer منتظر می‌ماند تا لیست مشترک items حداقل یک آیتم داشته باشد؛ این شرط دقیقاً همان چیزی است که wait_for بررسی می‌کند.

import asyncio
import random

async def producer(condition, items):
    for i in range(5):
        delay = random.uniform(0.2, 0.6)
        await asyncio.sleep(delay)
        async with condition:
            items.append(f'item-{i}')
            print(f'producer: تولید شد -> item-{i}')
            condition.notify()

async def consumer(condition, items):
    while True:
        async with condition:
            await condition.wait_for(lambda: len(items) > 0)
            item = items.pop(0)
            print(f'consumer: مصرف شد -> {item}')
        if item == 'item-4':
            break

async def main():
    condition = asyncio.Condition()
    items = []
    await asyncio.gather(
        producer(condition, items),
        consumer(condition, items)
    )

asyncio.run(main())

نکتهٔ مهم این است که condition.notify() باید درون همان بلوک async with صدا زده شود که داده‌های مشترک تغییر کرده‌اند؛ در غیر این صورت ممکن است Task منتظر هیچ‌گاه از تغییر باخبر نشود.

جمع‌بندی

کلاس Condition برای سناریوهایی مناسب است که Task‌ها باید منتظر برقراری یک شرط مشخص دربارهٔ داده‌های مشترک بمانند، نه فقط یک سیگنال ساده. در درس بعدی با متد shield آشنا می‌شویم که به ما اجازه می‌دهد بخشی از کد را در برابر لغو شدن (Cancellation) محافظت کنیم.

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

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

62%
پیشرفت

سرفصل دوره

فهرست مطالب

سرفصل دوره

تمرین

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

پاسخ تمرین ها

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

اشتراک گذاری

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

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

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

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

تنظیمات

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