Sobes.tech
Middle+

C# da bir nechta oqim umumiy holatga murojaat qilganda, oqimlar va vazifalar bilan qanday ishlash amalga oshiriladi?

sobes.tech AI

AIdan javob

C# tilida bir nechta oqimlar bilan umumiy holat bilan ishlashda sinxronizatsiya muammolari va raqiblik shartlari yuzaga kelishi mumkin. Oqimlarning xavfsizligini ta'minlash uchun quyidagi mexanizmlar ishlatiladi:

  1. Bloklash (Locking):

    • lock operatori yordamida tanqidiy bo'lim yaratiladi, bu faqat bitta oqim himoyalangan resursga kirish huquqiga ega bo'lishini kafolatlaydi.
    • Odatda private readonly object bo'lgan bloklash obyekti talab qilinadi va sinxronizatsiya uchun ishlatiladi.
    // lock misoli
    private readonly object _lockObject = new object();
    private int _sharedCounter = 0;
    
    public void IncrementCounter()
    {
        lock (_lockObject)
        {
            _sharedCounter++; // Tanqidiy bo'lim
        }
    }
    
  2. Atomik operatsiyalar:

    • System.Threading.Interlocked sinfi atomik operatsiyalarni (masalan, Increment, Decrement, Add, Exchange) taqdim etadi va bu oqim xavfsiz bo'lib, aniq bloklashsiz bajariladi.
    // Interlocked misoli
    private volatile int _sharedValue = 0; // volatile o'zgarishlarni ko'rish uchun
    
    public void UpdateValue(int newValue)
    {
        Interlocked.Exchange(ref _sharedValue, newValue); // Atomik tayinlash
    }
    
    public void IncrementValue()
    {
        Interlocked.Increment(ref _sharedValue); // Atomik oshirish
    }
    
    • volatile o'zgarishlarning oqimlar o'rtasida ko'rinishini ta'minlaydi, ammo ko'p bosqichli operatsiyalarni atomik qilishni kafolatlamaydi. Atomik operatsiyalar uchun Interlocked ishlatilishi kerak.
  3. System.Threading va System.Threading.Tasks dan sinxronizatsiya sinflari:

    • Monitor: lock ga nisbatan pastroq darajadagi blokirovka mexanizmi.
    • Mutex: bir nechta jarayonlar o'rtasida resursga kirishni sinxronlashtirish imkonini beradi.
    • SemaphoreSlim: bir vaqtning o'zida resursga kirish mumkin bo'lgan oqimlar sonini cheklaydi.
    • ReaderWriterLockSlim: ko'p oqimlar resursni o'qishi mumkin, lekin faqat bitta oqim yozishi mumkin.
  4. Oqim xavfsiz kolleksiyalar:

    • System.Collections.Concurrent nom space ichida maxsus ko'p oqimli kirish uchun mo'ljallangan kolleksiyalar (ConcurrentBag<T>, ConcurrentDictionary<TKey, TValue>, ConcurrentQueue<T>, ConcurrentStack<T>) mavjud. Bu kolleksiyalarni ishlatish asosiy operatsiyalar uchun qo'lda sinxronizatsiya qilish zaruratini yo'q qiladi.
    // ConcurrentDictionary misoli
    private ConcurrentDictionary<string, int> _sharedData = new ConcurrentDictionary<string, int>();
    
    public void AddOrUpdateData(string key, int value)
    {
        _sharedData.AddOrUpdate(key, value, (k, oldValue) => oldValue + value);
    }
    
  5. O'zgarmas obyektlar:

    • O'zgarmas obyektlar (immutable) yaratish, ular yaratildan so'ng holatini o'zgartirish mumkin emasligini anglatadi. Agar umumiy holat o'zgarmas obyekt bilan ifodalangan bo'lsa, ko'p oqimlar uni xavfsiz o'qishi mumkin va sinxronizatsiya qilish shart emas. Holatni yangilash yangi obyekt nusxasini yaratishga teng.

Task bilan ishlashda ham umumiy holatga kirish sinxronizatsiya qilishni talab qiladi. TPL (Task Parallel Library) parallel operatsiyalarni yaratish va boshqarishni soddalashtiradi, ammo umumiy ma'lumotlar bilan ishlashda oqim xavfsizligini ta'minlash mas'uliyatini olib tashlamaydi.

Mos sinxronizatsiya mexanizmini tanlash aniq vazifa va umumiy holatga kirish xususiyatlariga bog'liq.