Yarış koşulları ve kilitlenmeler

Visual Basic .NET veya Visual Basic, Visual Basic uygulamalarında iş parçacıklarını ilk kez kullanma olanağı sunar. İş parçacıkları, yarış koşulları ve kilitlenmeler gibi hata ayıklama sorunlarına neden olur. Bu makalede bu iki sorun ele alınıyor.

Orijinal ürün sürümü: Visual Basic, Visual Basic .NET
Özgün KB numarası: 317723

Yarış koşulları oluştuğunda

İki iş parçacığı paylaşılan bir değişkene aynı anda eriştiğinde bir yarış durumu oluşur. İlk iş parçacığı değişkeni okur ve ikinci iş parçacığı değişkenden aynı değeri okur. Ardından ilk iş parçacığı ve ikinci iş parçacığı değer üzerinde işlemlerini gerçekleştirir ve hangi iş parçacığının değeri paylaşılan değişkene en son yazabileceğini görmek için yarışırlar. İş parçacığı önceki iş parçacığının yazdığı değerin üzerine yazdığından, değerini en son yazan iş parçacığının değeri korunur.

Yarış durumu için ayrıntılar ve örnekler

Her iş parçacığı, bir işlemci üzerinde yürütülecek önceden tanımlanmış bir süre ayrılır. İş parçacığı için ayrılan süre dolduğunda, iş parçacığının bağlamı işlemciyi bir sonraki açıncaya kadar kaydedilir ve işlemci sonraki iş parçacığının yürütülmesine başlar.

Tek satırlık komut bir yarış durumuna nasıl neden olabilir?

Bir yarış durumunun nasıl oluştuğuna bakmak için aşağıdaki örneği inceleyin. İki iş parçacığı vardır ve her ikisi de toplam adlı paylaşılan bir değişkeni güncelleştirmektedir (derleme kodunda olduğu gibi dword ptr ds:[031B49DCh] gösterilir).

  • İş Parçacığı 1

    Total = Total + val1
    
  • İş Parçacığı 2

    Total = Total - val2
    

Önceki Visual Basic kodunun derlemesinden derleme kodu (satır numaralarıyla):

  • İş Parçacığı 1

    1. mov eax,dword ptr ds:[031B49DCh]
    2. add eax,edi
    3. jno 00000033
    4. xor ecx,ecx
    5. call 7611097F
    6. mov dword ptr ds:[031B49DCh],eax
    
  • İş Parçacığı 2

    1. mov eax,dword ptr ds:[031B49DCh]
    2. sub eax,edi
    3. jno 00000033
    4. xor ecx,ecx
    5. call 76110BE7
    6. mov dword ptr ds:[031B49DCh],eax
    

Derleme koduna bakarak, basit bir toplama hesaplaması yürütmek için işlemcinin alt düzeyde kaç işlem gerçekleştirdiğini görebilirsiniz. İş parçacığı, işlemci üzerinde olduğu süre boyunca derleme kodunun tamamını veya bir bölümünü yürütebilir. Şimdi bu koddan bir yarış durumunun nasıl oluştuğuna bakın.

Total 100, val1 50 ve val2 15. İş parçacığı 1 yürütme fırsatı alır ancak yalnızca 1 ile 3 arasındaki adımları tamamlar. Bu, İş Parçacığı 1'in değişkeni okuduğu ve toplamayı tamamlandığı anlamına gelir. İş parçacığı 1 artık 150 olan yeni değerini yazmak için bekliyor. İş Parçacığı 1 durdurulduktan sonra, İş Parçacığı 2 tamamen yürütülür. Bu, hesaplanan değeri (85) değişkenine Totalyazdığı anlamına gelir. Son olarak, İş Parçacığı 1 denetimi yeniden kazanır ve yürütmeyi tamamlar. Değerini (150) yazar. Bu nedenle, İş Parçacığı 1 tamamlandığında değeri Total artık 85 yerine 150 olur.

Bunun nasıl önemli bir sorun olabileceğini görebilirsiniz. Bu bir bankacılık programıysa, müşterinin hesabında mevcut olmaması gereken parası olacaktır.

İş Parçacığı 1'in işlemcinin süresi dolmadan önce yürütmesini tamamlaması ve ardından İş Parçacığı 2'nin yürütülmesine başlayabilmesi nedeniyle bu hata rastgeledir. Bu olaylar oluşursa sorun oluşmaz. İş parçacığı yürütmesi belirsizdir, bu nedenle yürütme zamanını veya sırasını denetleyemezsiniz. Ayrıca iş parçacıklarının çalışma zamanında ve hata ayıklama modunda farklı yürütülebileceğini unutmayın. Ayrıca, her iş parçacığını seri olarak yürütürseniz hatanın oluşmadığını da görebilirsiniz. Bu rastgelelik, bu hataların izlenmesini ve hata ayıklamasını çok daha zor hale getirir.

Yarış koşullarının oluşmasını önlemek için paylaşılan değişkenleri kilitleyerek aynı anda yalnızca bir iş parçacığının paylaşılan değişkene erişmesini sağlayabilirsiniz. İş Parçacığı 1'de bir değişken kilitliyse ve İş Parçacığı 2 de değişkene ihtiyaç duyduğundan, İş Parçacığı 2,İş Parçacığı1'in değişkeni serbest bırakmasını beklerken iş parçacığı 2'nin yürütmesi durdurulur. (Daha fazla bilgi için bu makalenin Başvurular bölümüne bakınSyncLock.)

Yarış durumu belirtileri

Bir yarış durumunun en yaygın belirtisi, birden çok iş parçacığı arasında paylaşılan değişkenlerin tahmin edilemeyen değerleridir. Bu, iş parçacıklarının yürütülme sırasının öngörülememesinden kaynaklanabilir. Bazen bir iş parçacığı kazanır, bazen de diğer iş parçacığı kazanır. Diğer zamanlarda yürütme düzgün çalışır. Ayrıca, her iş parçacığı ayrı olarak yürütülürse değişken değeri doğru şekilde davranır.

Kilitlenmeler oluştuğunda

İki iş parçacığının her biri aynı anda farklı bir değişkeni kilitleyip diğer iş parçacığının zaten kilitli olduğu değişkeni kilitlemeye çalıştığında kilitlenme oluşur. Sonuç olarak, her iş parçacığı yürütmeyi durdurur ve diğer iş parçacığının değişkeni serbest bırakmasını bekler. Her iş parçacığı diğer iş parçacığının istediği değişkeni tuttuğundan hiçbir şey gerçekleşmez ve iş parçacıkları kilitlenmeye devam eder.

Kilitlenmelerle ilgili ayrıntılar ve örnekler

Aşağıdaki kodun iki nesnesi LeftVal vardır ve RightVal:

  • İş Parçacığı 1

    SyncLock LeftVal
        SyncLock RightVal
            'Perform operations on LeftVal and RightVal that require read and write.
        End SyncLock
    End SyncLock
    
  • İş Parçacığı 2

    SyncLock RightVal
        SyncLock LeftVal
            'Perform operations on RightVal and LeftVal that require read and write.
        End SyncLock
    End SyncLock
    

İş Parçacığı 1'in kilitlenmesine LeftValizin verilirse kilitlenme oluşur. İşlemci , İş Parçacığı 1'in yürütmesini durdurur ve İş Parçacığı 2'nin yürütülmesini başlatır. İş parçacığı 2 kilitler RightVal ve sonra kilitlemeye LeftValçalışır. Kilitli LeftVal olduğundan , İş Parçacığı 2 durdurulur ve serbest bırakılmayı bekler LeftVal . İş Parçacığı 2 durdurulduğu için, İş Parçacığı 1'in yürütülmeye devam etme izni verilir. İş Parçacığı 2 kilitlendiğinden, İş Parçacığı 1 kilitlemeyi RightVal dener ancak kilitleyemez. Sonuç olarak, İş Parçacığı 1 RightVal kullanılabilir olana kadar beklemeye başlar. Her iş parçacığı diğer iş parçacığını bekler çünkü her iş parçacığı diğer iş parçacığının beklediği değişkeni kilitlemiştir ve her iki iş parçacığı da tuttuğu değişkenin kilidini açmaz.

Kilitlenme her zaman gerçekleşmez. İş Parçacığı 1, işlemci durdurmadan önce her iki kilidi de yürütürse, İş Parçacığı 1 işlemlerini gerçekleştirebilir ve ardından paylaşılan değişkenin kilidini açabilir. İş Parçacığı 1 değişkenin kilidini açtıktan sonra, İş Parçacığı 2 beklendiği gibi yürütmeye devam edebilir.

Bu kod parçacıkları yan yana yerleştirildiğinde bu hata belirgin görünür, ancak uygulamada kod, kodunuzun ayrı modüllerinde veya alanlarında görünebilir. Bu, aynı koddan hem doğru yürütme hem de yanlış yürütme gerçekleşebileceğinden izlenmesi zor bir hatadır.

Kilitlenme belirtileri

Kilitlenmenin yaygın bir belirtisi, programın veya iş parçacığı grubunun yanıt vermeyi durdurmasıdır. Bu, askıda kalma olarak da bilinir. En az iki iş parçacığı, diğer iş parçacığının kilitlediği bir değişkeni bekliyor. İş parçacıkları devam etmemektedir, çünkü diğer değişkeni alana kadar hiçbir iş parçacığı değişkenini serbest bırakmaz. Program yürütmeyi tamamlamak için bu iş parçacıklarından birini veya her ikisini bekliyorsa tüm program kilitlenebilir.

İş parçacığı nedir?

İşlemler, belirli bir zamanda yürütülen farklı uygulamaları tek bir bilgisayarda ayırmak için kullanılır. İşletim sistemi işlemleri yürütmez, ancak iş parçacıkları yürütür. İş parçacığı bir yürütme birimidir. İşletim sistemi, iş parçacığının görevlerinin yürütülmesi için bir iş parçacığına işlemci süresi ayırır. Tek bir işlem birden çok yürütme iş parçacığı içerebilir. her iş parçacığı kendi özel durum işleyicilerini, zamanlama önceliklerini ve iş parçacığının işlemciye atandığı süre boyunca yürütmesini tamamlayamazsa, işletim sisteminin iş parçacığının bağlamını kaydetmek için kullandığı bir dizi yapıyı korur. Bağlam, iş parçacığının işlemci süresini bir sonraki almasına kadar tutulur. Bağlam, iş parçacığının sorunsuz bir şekilde yürütmeye devam etmesi için gereken tüm bilgileri içerir. Bu bilgiler, iş parçacığının işlemci yazmaçları kümesini ve konak işleminin adres alanı içindeki çağrı yığınını içerir.

Başvurular

Daha fazla bilgi için aşağıdaki anahtar sözcükler için Visual Studio Yardımı'nı arayın:

  • SyncLock. Bir nesnenin kilitlenmesine izin verir. Başka bir iş parçacığı aynı nesneyi kilitlemeye çalışırsa, ilk iş parçacığı serbest bırakana kadar engellenir. Sorunlar SyncLock'un yanlış kullanımından kaynaklanabileceğinden dikkatli kullanın SyncLock . Örneğin, bu komut yarış koşullarını önleyebilir ancak kilitlenmelere neden olabilir.

  • InterLocked. Temel sayısal değişkenler üzerinde iş parçacığı güvenli işlemler kümesine izin verir.

Daha fazla bilgi için bkz. İş Parçacıkları ve İş Parçacığı Oluşturma.