Birisi arasındaki farkı açıklayabilir mi:
- kilitlemek (someobject) {}
- Mutex kullanma
- Semafor Kullanımı
- Monitörü Kullanma
- Diğer .Net senkronizasyon sınıflarını kullanma
Sadece anlayamıyorum. Bana öyle geliyor ki ilk ikisi aynı mı?
Birisi arasındaki farkı açıklayabilir mi:
Sadece anlayamıyorum. Bana öyle geliyor ki ilk ikisi aynı mı?
Yanıtlar:
Harika bir soru. Belki yanılıyorum .. Deneyeyim .. Orig cevabımın 2. revizyonu .. biraz daha anlayışla. Beni okuduğunuz için teşekkürler :)
Kilit (obj)
Monitörler
Bir kilit veya monitör kullanmak, iş parçacığına duyarlı kod bloklarının aynı anda yürütülmesini önlemek için yararlıdır, ancak bu yapılar bir iş parçacığının bir olayı diğerine iletmesine izin vermez. Bu, iş parçacıklarını etkinleştirmek ve askıya almak için kullanılabilen, iki durumdan birine sahip, sinyalli ve sinyalsiz nesneler olan senkronizasyon olaylarını gerektirir . Muteks, Semaforlar OS düzeyinde kavramlardır. örneğin adlandırılmış bir muteks ile birden çok (yönetilen) exe arasında senkronize edebilirsiniz (uygulamanızın yalnızca bir örneğinin makinede çalışmasını sağlar).
Karşılıklı dışlama:
Semaforlar (beynime zarar verdi).
Monitor
İletişime izin vermediğini iddia ediyorsunuz ; Hala Pulse
vb. yapabilirsinizMonitor
Yeniden "Diğer .Net senkronizasyon sınıflarını kullanma" - bilmeniz gereken diğerlerinden bazıları:
CCR / TPL'de ( Paralel Uzantılar CTP) daha fazla (düşük havai) kilitleme yapısı var - ancak IIRC, bunlar .NET 4.0'da kullanılabilir olacak
ECMA'da belirtildiği gibi, Yansıyan yöntemlerden de görebileceğiniz gibi, kilit ifadesi temel olarak
object obj = x;
System.Threading.Monitor.Enter(obj);
try {
…
}
finally {
System.Threading.Monitor.Exit(obj);
}
Yukarıda belirtilen örnekte, Monitörlerin nesneleri kilitleyebildiğini görüyoruz.
Onlar gibi işlemler arası eşitleme gerektiğinde Mutexe en yararlıdır edebilir bir dize tanımlayıcı kilidi. Aynı dize tanımlayıcısı, kilidi elde etmek için farklı işlemler tarafından kullanılabilir.
Semaforlar steroidler üzerindeki Muteksler gibidir, maksimum sayıda eşzamanlı erişim sağlayarak eşzamanlı erişime izin verir '. Sınıra ulaşıldığında, semafor, arayanlardan biri semaforu serbest bırakana kadar kaynağa daha fazla erişimi engellemeye başlar.
DotGNU'da diş açma için dersleri ve CLR desteği yaptım ve birkaç düşüncem var ...
Çapraz işlem kilitleri gerektirmedikçe Mutex & Semaphores kullanmaktan daima kaçınmalısınız. Bu .NET sınıfları Win32 Mutex ve Semaphores etrafındaki sarmalayıcılardır ve oldukça ağırdırlar (özellikle kilidiniz çekişme altında değilse, çekirdeğe pahalı bir bağlam anahtarı gerektirirler).
Diğerleri de belirtildiği gibi, C # lock deyimi Monitor.Enter ve Monitor.Exit için derleyici büyüsüdür (bir try / son olarak mevcuttur).
Monitörler, Mutexes'in Monitor.Pulse / Monitor.Wait yöntemleriyle sahip olmadığı basit ama güçlü bir sinyal / bekleme mekanizmasına sahiptir. Win32 eşdeğeri, aslında .NET'te WaitHandles olarak da bulunan CreateEvent aracılığıyla olay nesneleri olacaktır. Darbe / Bekleme modeli, Unix'in pthread_signal ve pthread_wait modellerine benzer, ancak daha hızlıdır, çünkü daha önce tartışılmamış durumda tamamen kullanıcı modu işlemleri olabilirler.
Monitor.Pulse / Wait kullanımı kolaydır. Bir iş parçacığında, bir nesneyi kilitleriz, bir bayrağı / durumu / özelliği kontrol ederiz ve beklediğimiz şey bu değilse, Monitor.Wit'i arayın, kilidi serbest bırakır ve bir nabız gönderilinceye kadar bekleyin. Bekleme geri döndüğünde, geri dönüp bayrağı / durumu / özelliği tekrar kontrol ederiz. Diğer iş parçacığında, flag / state / özelliği değiştirdiğimizde nesneyi kilitleriz ve ardından dinleme iş parçacıklarını uyandırmak için PulseAll'ı çağırırız.
Genellikle sınıflarımızın iş parçacığı için güvenli olmasını isteriz, bu yüzden kodumuza kilitler koyarız. Ancak, genellikle sınıfımızın yalnızca bir iş parçacığı tarafından kullanılması söz konusudur. Bu, kilitlerin kodumuzu gereksiz yere yavaşlattığı anlamına gelir ... CLR'deki akıllı optimizasyonlar performansın iyileştirilmesine yardımcı olabilir.
Microsoft'un kilitlerin uygulanmasından emin değilim ama DotGNU ve Mono'da kilit durum bayrağı her nesnenin başlığında saklanıyor. .NET'teki (ve Java'daki) her nesne bir kilit haline gelebilir, böylece her nesnenin bunu başlıklarında desteklemesi gerekir. DotGNU uygulamasında, kilit olarak kullanılan her nesne için genel bir hashtable kullanmanıza izin veren bir bayrak vardır - bu, her nesne için 4 baytlık bir ek yükü ortadan kaldırma avantajına sahiptir. Bu, bellek için harika değildir (özellikle ağır iş parçacığı olmayan gömülü sistemler için), ancak performansa sahiptir.
Hem Mono hem de DotGNU, kilitleme / bekleme gerçekleştirmek için muteksleri etkili bir şekilde kullanır, ancak bir spinlock stili karşılaştırma ve değiştirme kullanın gerçekten gerekli olmadıkça gerçekten bir sabit kilit gerçekleştirme ihtiyacını ortadan kaldırmak için işlemleri kullanır:
Monitörlerin nasıl uygulanabileceğine ilişkin bir örneği burada görebilirsiniz:
http://cvs.savannah.gnu.org/viewvc/dotgnu-pnet/pnet/engine/lib_monitor.c?revision=1.7&view=markup
Dize kimliğiyle tanımladığınız herhangi bir paylaşılan Mutex'i kilitlemek için ek bir uyarı, varsayılan olarak bir "Yerel \" muteksi olacak ve terminal sunucusu ortamındaki oturumlar arasında paylaşılmayacaktır.
Paylaşılan sistem kaynaklarına erişimin düzgün bir şekilde kontrol edilmesini sağlamak için dize tanımlayıcınıza "Global \" önekini ekleyin. Ben bunu fark etmeden önce sadece SİSTEM hesabı altında çalışan bir hizmet ile iletişimi senkronize sorunları bir yığın halinde çalışıyordu.
Eğer "lock ()", "Mutex" ve "Monitör" önlemek için çalışır ...
.NET 4'te yeni ad alanı System.Collections.Concurrent'a bakın.
Bazı iş parçacığı için güvenli koleksiyon sınıfları vardır
http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx
ConcurrentDictionary kayalar! Artık benim için manuel kilitleme yok!
Çoğu durumda olmamalıdır kilitleri (= Monitörler) ya da muteksler / semaforları kullanın. Hepsi mevcut iş parçacığını engeller.
Ve kesinlikle kullanmamalısın System.Collections.Concurrent
sınıfları - bunlar yarış koşullarının ana kaynağıdır çünkü birden fazla koleksiyon arasındaki işlemleri desteklemez ve aynı zamanda mevcut iş parçacığını engeller.
Şaşırtıcı bir şekilde .NET'in senkronizasyon için etkili mekanizmaları yoktur.
C # üzerinde GCD'den ( dünya) seri kuyruk uyguladım Objc/Swift
- çok hafif, testler ile iş parçacığı havuzu kullanan senkronizasyon aracını engellemiyor.
Çoğu durumda her şeyi senkronize etmenin en iyi yolu - veritabanı erişiminden (merhaba sqlite) iş mantığına.