این مقاله اولین قسمت از مجموعهای است که به بررسی APIهای همگامسازی در .NET میپردازد. در این قسمت، به همگامسازی درونفرآیندی (in-process synchronization) خواهیم پرداخت و در قسمتهای بعدی به موضوعات همگامسازی بینفرآیندی در یک ماشین و همگامسازی توزیعشده خواهیم پرداخت. هدف از این APIها، محدود کردن دسترسی به منابع مشترک و مدیریت همزمانی در برنامههای چندنخی است.
در .NET، مکانیسمهای همگامسازی درونفرآیندی برای محدود کردن دسترسی به منابع مشترک و مدیریت همزمانی در برنامههای چندنخی استفاده میشوند. این مکانیسمها فقط برای کد درونفرآیندی قابل استفاده هستند و برای همگامسازی چندین فرآیند در یک ماشین یا ماشینهای مختلف مناسب نیستند. اصطلاحات "قفلگذاری" (locking) و "همگامسازی بر روی" (synchronizing on) در این مقاله به جای یکدیگر استفاده میشوند.
همگامسازی نخها برای جلوگیری از بروز مشکلاتی مانند شرط مسابقه (race conditions)، خرابی دادهها (data corruption) و بنبست (deadlocks) ضروری است. شرط مسابقه زمانی رخ میدهد که دو نخ به طور همزمان سعی در تغییر یک داده مشترک داشته باشند. خرابی دادهها زمانی اتفاق میافتد که دادههای مشترک بین دو یا چند نخ ناسازگار شوند، زیرا یک نخ تغییراتی را اعمال میکند بدون اینکه نخ دیگر از آن آگاه باشد. بنبست زمانی رخ میدهد که دو یا چند نخ منتظر یکدیگر باشند.
مکانیسمهای مختلف قفلگذاری/کنترل دسترسی را میتوان به روشهای مختلفی گروهبندی کرد، از جمله دسترسی یکسان برای همه در مقابل دسترسیهای مختلف (خواندن/نوشتن)، دسترسی تکی به منبع مشترک در مقابل دسترسی همزمان چندگانه (تا حداکثر یک تعداد مشخص)، پشتیبانی از فراخوانیهای ناهمگام در مقابل فقط همگام، و عملکرد در سطح هسته سیستم عامل در مقابل سطح کاربر. در این مقاله به بررسی موارد زیر خواهیم پرداخت: دستور lock، کلاس Lock، کلاس Monitor، ویژگی MethodImpl، کلاس Mutex، کلاسهای Semaphore و SemaphoreSlim، کلاسهای ReaderWriteLock و ReaderWriterLockSlim، کلاسهای رویداد AutoResetEvent و ManualResetEvent، کلاس CountdownEvent، کلاسهای چرخش SpinLock و SpinWait.
دستور lock بخشی از زبان C# است و در واقع شکرگذاری نحوی برای کلاسهای Monitor یا Lock است. این دستور راهی ساده برای اطمینان از اجرای یک بلوک کد توسط تنها یک نخ در یک زمان فراهم میکند. این دستور یک قفل را بر روی یک شی خاص به دست میگیرد و زمانی که بلوک به پایان میرسد (حتی اگر یک استثنا پرتاب شود) آن را آزاد میکند.
مشاهده مطلب اصلی