2010-03-19 13 views
5

Bir similar question cevabını okuyordum, ama yine de biraz kafam karıştı ... Abel büyük bir cevabım vardı ama bu konuda emin değilim parçasıdır:Kilitli garanti C# diğer iş parçacıkları için görünürlük veya hala uçucu kullanmak zorunda mıyım?

.. Değişken bir uçucu maddenin değiştirilmesi, her bir erişimi için uçucu hale getirir. Bu davranışını başka herhangi bir şekilde zorlamak imkansızdır, dolayısıyla volatil , Interlocked ile değiştirilemez. Bu diğer kütüphaneler, arayüzler veya donanım Değişkeninizi erişebilir senaryolarda gerekli ve güncelleme bunu her zaman, ya da en yeni sürümüne ihtiyacınız olduğunu.

tüm dişlerine atom operasyon Interlocked garanti görünürlüğünü mu, ​​yoksa hâlâ değişim görünürlüğünü garanti altına almak için değeri volatile anahtar kelime kullanmak zorundayım? İşte

benim örnektir:

volatile int value = 100000; // <-- do I need the volitile keyword 
// .... 

public void AnotherThreadMethod() 
{ 
while(Interlocked.Decrement(ref value)>0) 
{ 
    // do something 
} 
} 


public void AThreadMethod() 
{ 
while(value > 0) 
{ 
    // do something 
} 
} 

Güncelleme: Kötü bir spor olduğunu ve orijinal örneği değişti
, işte yine o:

public class CountDownLatch 
{ 
    private volatile int m_remain; // <--- do I need the volatile keyword here? 
    private EventWaitHandle m_event; 

    public CountDownLatch(int count) 
    { 
     Reset(count); 
    } 

    public void Reset(int count) 
    { 
     if (count < 0) 
      throw new ArgumentOutOfRangeException(); 
     m_remain = count; 
     m_event = new ManualResetEvent(false); 
     if (m_remain == 0) 
     { 
      m_event.Set(); 
     } 
    } 

    public void Signal() 
    { 
     // The last thread to signal also sets the event. 
     if (Interlocked.Decrement(ref m_remain) == 0) 
      m_event.Set(); 
    } 

    public void Wait() 
    { 
     m_event.WaitOne(); 
    } 
} 
+0

Çoklu düzenlemeler için özür dilerim ... Remus bu konuda iyi bir spordur. Bilgi için teşekkürler! :) – Kiril

cevap

5

Onları yok * volatiliteye ihtiyaç duyarsınız, çünkü asla asla kilitlenmemiş değişkenin değerini kontrol etmeyin. Bunun yerine, her zaman kilitli işlem (ler) ile döndürülen değerini kontrol edin. Kilitli işlemleri karıştırma ve sıradan atama/karşılaştırma her zaman yanlış kodla sonuçlanır.

Sıfırla() işlev amacının ne olduğundan emin değilim, ancak söz konusu kod parçasının iş parçacığı arası ilkelde yeri yoktur: m_remain atarsanız, m_remain değerini doğrudan kontrol edersiniz, oldukça kötüdür. Bunu şiddetle tavsiye ediyorum: sadece yanlış uygulanmadığı gibi, yaşam boyu sürenin orta kısmına 'sıfırlama' semantiği gerektiğinden şüphe duyuyorum. Basit bırakın: ctor (Kodu Sıfırla'ya getirin) Sinyal ve Bekleyin gereken üç operatördür ve şu anda oldukları gibi doğrudurlar.

Güncelleme Kodu düzenledikten sonra.

İkisini karıştırmamanız gerektiği gerçeğini göz ardı ederseniz, onları karıştırırsanız evet, uçucu hala gereklidir. Uçucu, esas olarak, değerin her zaman gerçek bellek konumundan okunduğundan ve kodun yeniden sıralanması gibi bir optimizasyonun gerçekleşmediğinden emin olmak için oluşturulan IL kodu ve JIT koduyla ilgilidir. Birbirine bağlı olmayan bir kod parçasının Interlocked işlemlerini kullanarak değeri güncellemesi, değeri okuyan diğer parçalarda hiçbir etki yaratmaz. Bir volatile özniteliği ile, derleyici/JIT, başka bir yerde oluşan yazmaları yok sayan bir kod üretebilir, yazışmalar birbirine veya doğrudan atama ile alakasızsa.

BTW, normal okuma ve kilitleme işlemlerini karıştıran geçerli modeller vardır, ancak bunlar genellikle Interlocked.CompareExchange'i içerir ve şu şekilde davranırlar: geçerli durumu oku, geçerli duruma göre bazı hesaplamalar yapma, durumu bir kilitli durum olarak değiştirme girişiminde bulunma Karşılaştırma Değişimi: Eğer başarılı olursa, hesaplama sonucunu düşürmez ve 1. adıma dönersiniz.

+0

Eh, benim yazı lol önce hazırladım –

+0

Üzgünüm, örnek geri koymak ... Ben gerçekten seni kandırmak istemedim! :) – Kiril

+0

Bu yüzden Sıfırlama işlevi gidiyor ... gerçekten hiçbir anlam ifade etmedi. Aynı mandalı yeniden kullanmak için yararlı olabileceğini düşündüm, ama her şeyden daha fazla karışıklık katıyor. – Kiril

1

Bence System.Threading.Thread.VolatileRead (ref myVariable) aradığınız şey olabilir.Interlocked.Increment ile birlikte kullanıldığında, değişikliklerin atomik olduğunu ve okuduğunuz değerlerin en güncel olduğunu garanti etmek için kullanılabilir.

İlgili konular