Lock ve Mutex arasındaki fark nedir? Neden birbirlerinin yerine kullanılamıyorlar?
Lock ve Mutex arasındaki fark nedir? Neden birbirlerinin yerine kullanılamıyorlar?
Yanıtlar:
lock
bir derleyici anahtar sözcüktür, gerçek bir sınıf veya nesne değildir. Monitor
Sınıfın işlevselliği etrafında bir sarmalayıcıdır Monitor
ve genel durum için çalışmayı kolaylaştırmak için tasarlanmıştır .
Monitor
(Ve lock
Darin'in sınırlı olarak, sözü edilen anahtar) vardır AppDomain
. Öncelikle, "kilidi" yönetmek ve kimliğini korumak için bir bellek adresine (somutlaştırılmış bir nesne biçiminde) bir referans gerektiği içinMonitor
Mutex
Öte yandan, bir işletim sistemi yapısı etrafında Net sarıcı ve dize kullanarak, sistem genelinde senkronizasyon için kullanılabilen veri kimliğinin olarak (veriler yerine bir işaretçisi). Tamamen farklı iki bellek adresinde iki dizgeye başvuran, ancak aynı verilere sahip olan iki muteks, aslında aynı işletim sistemi muteksini kullanacaktır.
A Mutex
, bir süreç için yerel veya sistem genelinde olabilir . MSDN :
Muteksler iki tiptedir: adsız olan ve sistem muteksleri olarak adlandırılan yerel muteksler. Yerel bir muteks, yalnızca sizin sürecinizde vardır.
Ayrıca, Terminal Hizmetleri olan bir sistemde sistem çapında bir muteks kullanırken - aynı sayfada ayrıntıları da verilen - özel dikkat gösterilmelidir.
Arasındaki farklardan birisi Mutex
ve lock
olduğunu Mutex
bir kullanan çekirdek düzeyinde yapı senkronizasyon her zaman en azından bir kullanıcı alanı-çekirdek alanı geçişi gerektirecektir, bu yüzden.
lock
- bu gerçekten Monitor
sınıfa giden bir kısayoldur , diğer yandan çekirdek kaynaklarını tahsis etmekten ve çekirdek koduna geçmekten kaçınmaya çalışır (ve bu nedenle daha yalın ve daha hızlıdır - eğer benzeyen bir WinAPI yapısı bulmak gerekirse, olur CriticalSection
).
Diğer fark, diğerlerinin işaret ettiği şeydir: bir isim Mutex
, süreçler arasında kullanılabilir.
Kişinin özel ihtiyaçları olmadıkça veya işlemler arasında senkronizasyon gerektirmedikçe, lock
(aka Monitor
) ' ye bağlı kalmak daha iyidir ˛
Terk edilmenin nasıl ele alınacağı vb. Gibi birkaç başka "küçük" farklılık vardır.
3.5 için de aynısı söylenebilir ReaderWriterLock
ve .NET 4.0 vb. İçin de yenisi . İkinci sınıfların sistem çapında senkronizasyon ilkelleri olarak kullanılamayacağı doğrudur , ancak asla amaçlanmamıştır - "sadece" daha hızlı ve daha kaynak dostu olmak.ReaderWriterLockSlim
Semaphore
SemaphoreSlim
xxSlim
Aynı makinede çalışan uygulamanın bir kopyasına zaten sahip olup olmadığımı kontrol etmek için bir Mutex kullanıyorum.
bool firstInstance;
Mutex mutex = new Mutex(false, @"Local\DASHBOARD_MAIN_APPLICATION", out firstInstance);
if (!firstInstance)
{
//another copy of this application running
}
else
{
//run main application loop here.
}
// Refer to the mutex down here so garbage collection doesn't chuck it out.
GC.KeepAlive(mutex);
Şimdiden çok şey söylendi, ancak basitleştirmek için işte benim alacağım.
lock -> Kullanımı basit, monitörde sarıcı, bir AppDomain'deki iş parçacıkları arasında kilitlenir.
adsız mutex -> kilitleme kapsamının daha fazla olması dışında kilide benzer ve bir işlemde AppDomain genelinde bulunur.
Adlandırılmış mutex -> kilitleme kapsamı, adlandırılmamış bir muteksten bile daha fazlasıdır ve bir işletim sistemindeki süreç boyunca geçerlidir.
Artık seçenekler var, durumunuza en uygun olanı seçmeniz gerekiyor.
Mutex bir çapraz işlemdir ve bir uygulamanın birden fazla örneğini çalıştırmamanın klasik bir örneği olacaktır.
İkinci örnek, bir dosyaya sahip olduğunuzu ve aynı dosyaya erişmek için farklı bir işlem istemediğinizi, bir Mutex uygulayabileceğinizi ancak bir şeyi unutmayın Mutex'in işletim sistemi çapında olduğunu ve iki uzak işlem arasında kullanılamayacağını unutmayın.
Kilit, kodunuzun bir bölümünü korumanın en basit yoludur ve uygulamaya özgüdür, daha kontrollü senkronizasyon istiyorsanız kilidi Moniters ile değiştirebilirsiniz.
Cevaplarda bahsedilmeyen birkaç küçük farklılık daha var:
Kilitleri kullanılması durumunda, kilit olacaktır emin olabilirsiniz yayımlanan bir istisna kilidin bloğunun içinde gerçekleştiğinde.
Kaputun altında kilit kullandığı izler ve uygulanan Bunun nedeni bu şekilde:
object __lockObj = x;
bool __lockWasTaken = false;
try
{
System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
// Your code...
}
finally
{
if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}
Böylece, her durumda, kilit serbest bırakılır ve manuel olarak serbest bırakmanıza gerek yoktur (muteksler için yaptığınız gibi).
Kilitler için, genellikle kilitlemek için özel bir nesne kullanırsınız (ve kullanmanız gerekir ).
Bu birçok nedenden dolayı yapılır. (Daha fazla bilgi: bu yanıta ve resmi belgelere bakın ).
Yani kilitlenme durumunda kilitli nesneye dışarıdan (kazayla) erişemezsiniz ve bir miktar zarar veremezsiniz .
Ancak Mutex durumunda, herkese açık olarak işaretlenen ve her yerden kullanılan bir Mutex'e sahip olmak yaygın olduğu için yapabilirsiniz.