2011-08-01 26 views
6

aşağıdaki ECMA-335 özellikleri durumları: bir kilit edinme (System.Threading.Monitor.Enter veya senkronize bir yöntem giren)Kilitleme Monitor.Enter ve Monitor.Exit blok

* dolaylı uçucu bir okuma yapar işlem ve bir kilidi serbest bırakma (System.Threading.Monitor.Exit veya bir senkronize yöntem bırakarak), dolaylı olarak bir uçucu yazma işlemi gerçekleştirecektir. (...)

bir kalıcı salt okuma öncesi CIL talimat dizisi okuma talimatı sonra meydana bellek herhangi bir referans için cereyan etmesi garanti edifmektedir yani anlam kazanır sahiptir. Uçucu bir yazma, semantiklerin salıverilmesi anlamına gelir, bu da yazımın, CIL talimat dizisindeki yazma talimatından önce herhangi bir hafıza referansından sonra gerçekleşeceğinin garantilenmesi anlamına gelir. *

Bu, derleyicilerin ifadeleri Monitor.Enter/Monitor.Exit bloklarından dışarı taşıyamayacağı anlamına gelir, ancak diğer ifadelerin bloğa taşınması yasaktır. Belki de, başka bir Monitor.Enter bile blok içine taşınmış olabilir (uçucu yazma tarafından izlenen bir uçucu okuma olarak değiştirilebilir). Yani, aşağıdaki kod içerebilir:

class SomeClass 
{ 
    object _locker1 = new object(); 
    object _locker2 = new object(); 

    public void A() 
    { 
     Monitor.Enter(_locker1); 
     //Do something 
     Monitor.Enter(_locker2); 
     Monitor.Exit(_locker1); 
     //Do something 
     Monitor.Exit(_locker2); 
    } 

    public void B() 
    { 
     Monitor.Enter(_locker2); 
     //Do something 
     Monitor.Enter(_locker1); 
     Monitor.Exit(_locker2); 
     //Do something 
     Monitor.Exit(_locker1); 
    } 
} 

, muhtemelen kilitlenmeleri giden:

class SomeClass 
{ 
    object _locker1 = new object(); 
    object _locker2 = new object(); 

    public void A() 
    { 
     Monitor.Enter(_locker1); 
     //Do something 
     Monitor.Exit(_locker1); 
     Monitor.Enter(_locker2); 
     //Do something 
     Monitor.Exit(_locker2); 
    } 

    public void B() 
    { 
     Monitor.Enter(_locker2); 
     //Do something 
     Monitor.Exit(_locker2); 
     Monitor.Enter(_locker1); 
     //Do something 
     Monitor.Exit(_locker1); 
    } 
} 

, followig bir eşdeğerine dönüştürülebilir? Yoksa hiçbir şey eksik miyim?

+0

İki farklı şey hakkında konuşuyorsunuz. İlgili olan, ne derleyici ne de jitter, metod çağrılarını yeniden sipariş edemez. –

+0

Hmm ... ilginç bir soru. Yine de henüz argüman yeniden sıralama argümanını almaya hazırım. Demek istediğim, en iyi duruma getirme optimizasyonu * önleme optimizasyonundan önce. Spesifikasyonda bunu engelleyecek bir madde var mı? –

cevap

2

ECMA-335 özellikleri what the CLR (and every other implementation) uses'dan daha zayıftır.

Daha zayıf bir bellek modeli kullanarak, Microsoft'un IA-64'e ilk giriş yapma girişimi hakkında (heresay) okumayı hatırlıyorum.Çift kodlu kilitleme deyimine (daha zayıf bellek modeli altında bulunan is broken) bağlı olarak kendi kodlarının çokluğu vardı, bu platformda daha güçlü bir model oluşturdular.

Joe Duffy, sadece ölümlüler için (gerçek) CLR bellek modelini özetleyen a great post'a sahiptir. Ayrıca, CLR'nin ECMA-335'ten nasıl farklı olduğunu açıklayan bir MSDN makalesinin bir bağlantısı da vardır.

Pratikte bir sorun olduğuna inanmıyorum; Herkesin yaptığı gibi sadece CLR hafıza modelini al. Bu noktada hiç kimse zayıf bir uygulama yaratamazdı, çünkü çoğu kod sadece kırılırdı.

+0

Gerçekten de bu her yerde işe yaramadıysa, felaket etkisi olacaktır. – XanderMK

1

Eğer lock veya Monitor.Enter ve Monitor.Exit bu o beggening bellekte Thread.MemoryBarrier() bir "bariyer" veya kilidi "Monitor.Enter" ve kilit "Monitor.Exit" bitmeden yaratacak demek tam çitler olduğunu kullanın . Yani hiçbir işlem kilidi'dan önce ve sonra hareket etmeyecek, ancak kilidin içindeki işlemlerin diğer konuların perspektiflerinden değiştirilebileceğini unutmayın, ancak kilit, karşılıklı münhasır garanti edeceğinden bu bir sorun olmamıştır, bu yüzden sadece bir iş parçacığı olacaktır Kodu aynı anda kilit içinde yürütür. Yine de, yeniden sıralama, tek bir iş parçacığı içinde gerçekleşmeyecektir, yani, çoklu kodlu aynı kod bölgesini girdiklerinde, , numaralı talimatlara aynı sırada olmayan talimatlar verebilir.

this makalesinde MemoryBarrier ve tam ve yarım çitler hakkında daha fazla bilgi edinmenizi öneririz.

Düzenleme: çünkü @Hans gibi lock tam çit olduğu gerçeğini açıklayan, ancak farkında "ölü kilit", sen oluşur asla tarif senaryo söz etmiyorum burada Not sözü yaşayacakları bir yöntem çağrıları için oluşur asla yeniden sıralama, yani:

Method1(); 
Method2(); 
Method3(); 

.. hep sırayla çalıştırır, ancak Method1() içindedir kodu çalıştırmak çoklu işlemli zaman gibi içlerindeki talimatları yeniden sıralamak olabilir

+2

Evet, birçok kaynak Monitor.Enter ve Monitor.Exit'in tam bellek çitler olduğunu belirtiyor, ancak ECMA-335 belirtiminin kendisi başlangıçta ve bitişte yalnızca yarım çitler sağlar. Bununla birlikte, ECMA-335'ten daha katı olduğu için Microsoft uygulamasında hala haklı olabilirsiniz. Bu sorunun teoriden pratikten ziyade daha fazla olduğunu kabul ediyorum, fakat başka bir CLI uygulaması daha az katı olabilir, bu yüzden soru hala açık kalır. – XanderMK