SORU
3 Aralık 2012, PAZARTESİ


Nasıl bir dondurma dondurmak için .NET bir sınıf yapmak değişmez)

Ana bir konu bittikten sonra salt okunur yapılandırma yapmak istediğim bir sınıf tasarlıyorum, yani "dondurma". Eric Lippert popsicle Bu değişmezliğini tanıdı çağırır. Dondurulmuş sonra, okuma için aynı anda birden çok iş parçacığı tarafından erişilebilir.

Benim sorum iş parçacığı güvenli bir şekilde bunu nasıl yazacağımgerçekçiyani verimli gereksiz . yapmaya çalışmadan ^em>zeki.

Deneme 1:

public class Foobar
{
   private Boolean _isFrozen;

   public void Freeze() { _isFrozen = true; }

   // Only intended to be called by main thread, so checks if class is frozen. If it is the operation is invalid.
   public void WriteValue(Object val)
   {
      if (_isFrozen)
         throw new InvalidOperationException();

      // write ...
   }

   public Object ReadSomething()
   {
      return it;
   }
}

Eric Lippert bu this yazı TAMAM olur önermek gibi görünüyor. Yazar semantik bırakın, ama bu sadece ilgili anladığım kadarıyla gerektiğini biliyorumsiparişhemen yazdıktan sonra , mutlaka bütün konuları değer göreceği anlamına gelmez. Herkes bu teyit edebilir? Bu çözüm, iş parçacığı güvenli değil (bu tabii ki tek sebebi bu olmayabilir) anlamına gelir.

Girişimi 2:

Yukarıda, ama Interlocked.Exchange değeri aslında yayınlanmaktadır sağlamak için kullanma

public class Foobar
{
   private Int32 _isFrozen;

   public void Freeze() { Interlocked.Exchange(ref _isFrozen, 1); }

   public void WriteValue(Object val)
   {
      if (_isFrozen == 1)
         throw new InvalidOperationException();

      // write ...
   }
}

Avantaj burada biz değer her okumaya yükü uğramadan yayımlanır emin olun. Eğer hiçbiri Kilitli yöntemi Tam bir bellek engeli kullanır gibi _isFrozen için yazmadan önce taşınır yazıyorsa bu iş parçacığı güvenli olduğunu tahmin ediyorum. Ancak, kim derleyici (C, bölüm 3.10 oldukça çok gibi görünüyor# spec) göre ne bilir, bu yüzden bu iş parçacığı için güvenli olup olmadığını bilmiyorum.

Girişimi 3:

Ayrıca okuma Interlocked kullanarak.

public class Foobar
{
   private Int32 _isFrozen;

   public void Freeze() { Interlocked.Exchange(ref _isFrozen, 1); }

   public void WriteValue(Object val)
   {
      if (Interlocked.CompareExchange(ref _isFrozen, 0, 0) == 1)
         throw new InvalidOperationException();

      // write ...
   }
}

Güvenli, ama biraz savurgan yapmak zorunda gibi görünüyor kesinlikle iplik her okumak için exchange karşılaştırın. Bu yükü büyük bir olasılıkla çok az olduğunu biliyorum, ama bir şey arıyorummakuletkili yöntem (ancak belki de bu).

Girişimi 4:

volatile kullanarak:

public class Foobar
{
   private volatile Boolean _isFrozen;

   public void Freeze() { _isFrozen = true; }

   public void WriteValue(Object val)
   {
      if (_isFrozen)
         throw new InvalidOperationException();

      // write ...
   }
}

Ama Joe Duffy "sayonara volatile", yani bu bir çözüm düşünemez. ilan

Girişim 5:

Herşeyi kilitleyin, biraz abartı olmuş:

public class Foobar
{
   private readonly Object _syncRoot = new Object();
   private Boolean _isFrozen;

   public void Freeze() { lock(_syncRoot) _isFrozen = true; }

   public void WriteValue(Object val)
   {
      lock(_syncRoot) // as above we could include an attempt that reads *without* this lock
         if (_isFrozen)
            throw new InvalidOperationException();

      // write ...
   }
}

Ayrıca kesinlikle parçacığı güvenli görünüyor, ama yukarıda Kilitli yaklaşım kullanarak daha fazla yük vardır, bu girişimi 3 destek olurdum.

Ve o zaman en azından biraz daha (çok daha fazla olduğuna eminim) gelebilirim:

Girişim 6:Thread.VolatileWrite Thread.VolatileRead, ama bu ağır tarafında biraz güya.

Girişimi 7:Thread.MemoryBarrier, biraz fazla gibi kullanın.

Girişimi 8:değişmez bir kopyasını oluşturmak - bunu yapmak istemiyorum

Özetlersek:

  • hangi girişimi kullanırsınız ve neden (veya nasıl tamamen farklı ise)? sonra aşırı olmadan oldukça etkili olurken aynı anda Okuma, bir değer bir kez yayınlamak için en iyi yolu nedir (yani""?) zeki
  • yok .NET bellek modeli "" yazar semantik diğer tüm iş parçacıkları güncellemeleri (önbellek tutarlılık, vb.) ima? bırakın Ben genelde çok fazla bu konuda düşünmek istemiyorum, ama iyi bir anlayışa sahip.

DÜZENLEME:

Belki de sorumu net değildi, ama yukarıdaki girişimleri iyi ya da kötü neden olarak bir sebep için özellikle arıyorum. İşte o zaman donuyor herhangi bir eşzamanlı okur önce yazan tek bir yazar bir senaryo bahsediyorum unutmayın. Deneme 1 TAMAM ama eğer okur uzak bir şekilde, örneğin iyileştirilmiş acaba gibi) tam olarak neden bilmek istiyorum inanıyorum. Ya bu iyi tasarım uygulama ama daha fazla olup olmadığı hakkında az gerçek iş parçacığı yönünü önemsiyorum.


Bu soru, ama cevap verilmiş değil hissediyorum çünkü bir cevap olarak işaretlemek için kendime seçtiğim cevap için çok teşekkürleroldukçasoruma cevap ver ve sadece otomatik olarak bu ödül süreleri nedeniyle olarak işaretlenmiş çünkü İşaretlenen cevap doğru olduğunu herkes sitesini ziyaret izlenim vermek istemiyorum. Ayrıca en yüksek oyu ile cevap ezici bir oy, bir cevap olarak otomatik olarak işaretlemek için yeterli olduğunu düşünmüyorum.

Hala #1 doğru olma girişimi için çok sebebim var, ancak, bazı güvenilir cevap isterdi. 86 güçlü bir model olduğunu anlıyorum, ama güzel şeylerden biri olan (ve olmamalıdır) belirli bir mimari için, sonra da tüm kod istemiyorum .NET.

Eğer cevap konusunda şüpheniz varsa, kilitleme yaklaşımlar, belki iyileştirmeleri kilit çekişme çok önlemek için burada gösterilen biri.

CEVAP
12 Aralık 2012, ÇARŞAMBA


Belki meraktan konu ama sadece biraz) Neden "gerçek" değişmezliğini tanıdı? sen kullanmıyorsun örneğin yapımı Dondurma() değişmez bir kopyasını ("yazma" veya iç durumunu değiştirmek için başka bir olasılık) ve orijinal nesnenin yerine bu kopya yöntemleri kullanarak. bir şekilde geri dönmüş Devlet değiştirmeden git ve yeni bir kopyasını (değişik devlet ile her işlemi yerine write (afaık string sınıfı bu işleri) iade edebilirsiniz. "Gerçek değişmezliğini tanıdı" doğal olarak, iş parçacığı güvenli değil.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Google Chrome

    Google Chrom

    1 EYLÜL 2008
  • NightShader1

    NightShader1

    25 Temmuz 2006
  • Snazzy Labs

    Snazzy Labs

    9 Aralık 2008