.Net iş parçacığı senkronizasyonu için en iyi uygulamalar

Senkronizasyon, birden çok iş parçacığının aynı anda paylaşılan bir kaynağa erişmesini önlemek için kullanılan bir kavramdır. Birden çok iş parçacığının bir nesnenin özelliklerini veya yöntemlerini aynı anda çağırmasını önlemek için kullanabilirsiniz. Tek yapmanız gereken, paylaşılan kaynağa erişen kod bloğunu senkronize etmek veya çağrıları nesnenin özelliklerine ve üyelerine senkronize etmektir, böylece herhangi bir zamanda kritik bölüme yalnızca bir iş parçacığı girebilir.

Bu makale .Net'te senkronizasyon ve iş parçacığı güvenliği ile ilgili kavramlar ve ilgili en iyi uygulamalar hakkında bir tartışma sunar.

Özel kilit

Özel kilitleme, herhangi bir zamanda, bir ve yalnızca bir iş parçacığının kritik bir bölüme girebilmesini sağlamak için kullanılır. Uygulamanıza özel kilitler uygulamak için aşağıdakilerden birini kullanmanız gerekir.

  • Kilit - bu, Monitor sınıfının statik yöntemleri için sözdizimsel bir kısayoldur ve paylaşılan bir kaynakta özel bir kilit elde etmek için kullanılır
  • Mutex - birden fazla işlemde çalışabilmesi dışında kilit anahtar kelimesine benzer
  • SpinLock - iş parçacığı bağlam anahtarı ek yükünden kaçınarak paylaşılan bir kaynakta özel bir kilit elde etmek için kullanılır

Uygulamalarınızda iş parçacığı güvenliğini uygulamak için Monitor sınıfının statik yöntemlerini veya kilit anahtar sözcüğünü kullanabilirsiniz. Hem Monitor sınıfının statik üyeleri hem de kilit anahtar sözcükleri, paylaşılan bir kaynağa eşzamanlı erişimi önlemek için kullanılabilir. Lock anahtar sözcüğü, senkronizasyon gerçekleştirmenin yalnızca bir kısayol yoludur. Ancak, çok iş parçacıklı bir uygulamada karmaşık işlemler yapmanız gerektiğinde, Monitor sınıfının Wait () ve Pulse () yöntemleri yararlı olabilir.

Aşağıdaki kod parçacığı, Monitor sınıfını kullanarak senkronizasyonu nasıl uygulayabileceğinizi gösterir.

private static readonly object lockObj = new object();

        static void Main(string[] args)

        {

            Monitor.Enter(lockObj);

                       try

            {

               //Some code

            }

                  finally

            {

                Monitor.Exit(lockObj);

            }

        }

Lock anahtar sözcüğünü kullanan eşdeğer kod şuna benzer görünecektir:

    private static readonly object lockObj = new object();

        static void Main(string[] args)

        {  

            try

            {

                lock(lockObj)

                {

                    //Some code

                }             

            }

            finally

            {

                //You can release any resources here

            }

        }

Süreçler arasında yayılabilen senkronizasyon uygulamak için Mutex sınıfından yararlanabilirsiniz. Lock ifadesine benzer şekilde, bir Mutex tarafından elde edilen bir kilidin yalnızca kilidi elde etmek için kullanılan aynı iş parçacığından serbest bırakılabileceğini unutmayın. Mutex kullanarak kilitleri edinmek ve serbest bırakmak, aynı şeyi lock deyimi kullanarak yapmaktan nispeten daha yavaştır.

SpinLock'un arkasındaki ana fikir, iş parçacıkları arasında bağlam geçişinde yer alan maliyeti en aza indirmektir - bir iş parçacığı paylaşılan bir kaynak üzerinde bir kilit elde edene kadar bir süre bekleyebilir veya dönebilirse, iş parçacıkları arasında bağlamla ilgili ek yükten kaçınılabilir. . Kritik bölüm minimum miktarda çalışma yaptığında, SpinLock için iyi bir aday olabilir.

Özel olmayan kilit

Eşzamanlılığı sınırlandırmak için özel olmayan kilitlemeden yararlanabilirsiniz. Özel olmayan kilitleri uygulamak için aşağıdakilerden birini kullanabilirsiniz.

  • Semafor - aynı anda paylaşılan bir kaynağa erişebilen iş parçacığı sayısını sınırlamak için kullanılır. Temelde, belirli bir paylaşılan kaynak için tüketici sayısını eşzamanlı olarak sınırlamak için kullanılır.
  • SemaphoreSlim - münhasır olmayan kilitleri uygulamak için Semaphore sınıfına hızlı, hafif bir alternatif.
  • ReaderWriterLockSlim - ReaderWriterLockSlim sınıfı, .Net Framework 3.5'te ReaderWriterLock sınıfının yerine geçmiştir.

ReaderWriterLockSlim sınıfını, sık okunan ancak sık olmayan güncellemeler gerektiren paylaşılan bir kaynakta özel olmayan bir kilit elde etmek için kullanabilirsiniz. Bu nedenle, sık okuma ve sık olmayan güncellemeler gerektiren paylaşılan bir kaynakta karşılıklı olarak özel bir kilit yerine, bu sınıfı paylaşılan kaynakta bir okuma kilidi ve üzerinde özel bir yazma kilidi elde etmek için kullanabilirsiniz.

Kilitlenmeler

Kilitlenme durumlarına neden olabileceğinden, uygulamanızda senkronizasyonu uygulamak için tür veya kullanım ifadelerinde lock (this) gibi bir kilit ifadesi kullanmaktan kaçınmalısınız. Paylaşılan bir kaynakta edinilen kilidi daha uzun süre tuttuğunuzda da kilitlenmelerin ortaya çıkabileceğini unutmayın. Kilit ifadelerinizde değişmez türler kullanmamalısınız. Örnek olarak, bir dizgi nesnesini kilit ifadenizde anahtar olarak kullanmaktan kaçınmalısınız. Lock ifadesini genel bir türde kullanmaktan kaçınmalısınız - gizli veya korumalı olmayan özel veya korumalı nesneleri kilitlemek iyi bir uygulamadır. Temelde, birden fazla iş parçacığı birbirinin paylaşılan bir kaynak üzerindeki kilidi açmasını beklediğinde bir kilitlenme durumu oluşur. Kilitlenmeler hakkında daha fazla bilgi edinmek için bu MSDN makalesine başvurabilirsiniz.