github |
---|
true |
پیمان: 😕 بچهها، من یه مشکل عجیب پیدا کردم. وقتی چند تا کاربر همزمان درخواست تاکسی میزنن، بعضی وقتها تعداد تاکسیهای موجود اشتباه میشه. مثلاً وقتی دو نفر همزمان درخواست میزنن، ممکنه هر دو فکر کنن که تاکسی موجود هست و در نهایت یکی از اونها بیتاکسی بمونه.
حسین: 🤔 اوه، این میتونه نشونه یک race condition باشه. میتونی بیشتر توضیح بدی که دقیقاً چه اتفاقی میفته؟
پیمان: خب، فرض کن 5 تا تاکسی داریم. کاربر A و کاربر B همزمان درخواست میزنن. هر دو همزمان تعداد تاکسیهای موجود رو میخونن (که 5 تاست). هر دو فکر میکنن که میتونن یکی از تاکسیها رو بگیرن. اما در نهایت، یکی از اونها ممکنه بیتاکسی بمونه!
ماهان: 😮 یعنی یکی از درخواستها گم میشه؟ چطور همچین چیزی ممکنه؟
حسین: 👨🏫 این دقیقاً یه نمونه کلاسیک از race condition هست. بذارید براتون توضیح بدم.
کیان: 🤔 ببخشید حسین جون، میشه اول بگی race condition چیه؟ چرا بهش میگن "race"?
حسین: 😊 البته کیان جان! خوشحالم که پرسیدی.
این Race condition یه وضعیته که توش، نتیجه یه عملیات به ترتیب یا زمانبندی رویدادهای دیگه بستگی داره. مثل اینه که دو تا دونده با هم مسابقه بدن و نتیجه به این بستگی داشته باشه که کی زودتر به خط پایان برسه. در برنامهنویسی، این اتفاق معمولاً وقتی میفته که چند تا thread یا process سعی میکنن همزمان به یه منبع مشترک دسترسی پیدا کنن یا اون رو تغییر بدن.
حالا، بذارید مشکل پیمان رو با یه مثال ساده توضیح بدم:
- فرض کنید ما 5 تا تاکسی داریم.
- کاربر A و کاربر B همزمان درخواست میزنن.
- هر دو همزمان تعداد تاکسیها رو میخونن (که 5 تاست).
- هر دو فکر میکنن که میتونن یک تاکسی بگیرن.
- هر دو موجودی رو 1 تا کم میکنن.
- در نهایت، به جای اینکه 4 تا بمونه، ممکنه هر دو فکر کنن که درخواستشون پذیرفته شده و یکی از اونها بیتاکسی بمونه!
پیمان: 😲 دقیقاً! همین اتفاق داره میفته. چطور میتونیم حلش کنیم؟
حسین: برای حل این مشکل، ما نیاز داریم که عملیات خواندن و نوشتن موجودی رو "اتمیک" کنیم. یعنی مطمئن بشیم که هیچ عملیات دیگهای نمیتونه وسط این فرآیند مداخله کنه.
ماهان: 🤔 چطوری میتونیم این کار رو انجام بدیم؟
حسین: یکی از راهحلها استفاده از "lock" یا "mutex" هست. اینا مکانیزمهایی هستن که اجازه میدن فقط یک thread در یک زمان به یه منبع خاص دسترسی داشته باشه.
کیان: 😃 یعنی مثل اینه که روی در انبار یه قفل بذاریم و هر کی میخواد وارد بشه، باید صبر کنه تا نفر قبلی بیاد بیرون؟
حسین: 😃 آفرین کیان! دقیقاً همینطوره. خیلی خوب متوجه شدی.
پیمان: این عالیه! میتونی یه مثال کد بزنی که نشون بده چطور میتونیم این رو پیادهسازی کنیم؟
حسین: البته! بذارید یه مثال ساده با پایتون بزنم.
فرض کنید ما از threading و Lock استفاده میکنیم:
import threading
class TaxiService:
def __init__(self):
self.available_taxis = 5
self.lock = threading.Lock()
def request_taxi(self):
with self.lock:
if self.available_taxis > 0:
print("Taxi has been allocated.")
self.available_taxis -= 1
print(f"Remaining taxis: {self.available_taxis}")
else:
print("No taxis available.")
# ایجاد یک شیء از کلاس TaxiService
taxi_service = TaxiService()
# تعریف یک فانکشن برای درخواست تاکسی
def make_request():
taxi_service.request_taxi()
# ایجاد دو thread برای شبیهسازی درخواست همزمان
thread1 = threading.Thread(target=make_request)
thread2 = threading.Thread(target=make_request)
# شروع threadها
thread1.start()
thread2.start()
# منتظر ماندن برای اتمام threadها
thread1.join()
thread2.join()
حسین:
توی این مثال، ما از یک Lock
استفاده کردیم تا مطمئن بشیم که فقط یک thread در هر زمان میتونه به تعداد تاکسیها دسترسی داشته باشه.
این کار باعث میشه که race condition اتفاق نیفته.
کیان: 😮 وای، حالا فهمیدم! یعنی با این قفل، هیچ دو نفری نمیتونن همزمان به تعداد تاکسیها دسترسی پیدا کنن.
حسین: 👍 دقیقاً کیان جان! این یکی از راههای مهم برای جلوگیری از race condition هست. هر وقت سوال دیگهای داشتی، حتماً بپرس!
پیمان: مرسی حسین! این خیلی کمک کرد. حالا میتونم این مشکل رو توی کدمون حل کنم.