Kilit, muteks, semafor… fark nedir?


Yanıtlar:


534

Kilit, kilitlenen parçaya yalnızca bir iş parçacığının girmesine izin verir ve kilit başka işlemlerle paylaşılmaz.

Muteks kilitle aynıdır ancak sistem çapında olabilir (birden çok işlemle paylaşılabilir).

Bir semafor bir muteks ile aynı şeyi yapar ancak x iş parçacığının girmesine izin verir, bu örneğin aynı anda çalışan cpu, io veya ram yoğun görevlerin sayısını sınırlamak için kullanılabilir.

Muteks ve semafor arasındaki farklar hakkında daha ayrıntılı bir yazı için burayı okuyun .

Ayrıca, herhangi bir zamanda sınırsız sayıda okuyucuya veya 1 yazara izin veren okuma / yazma kilitleriniz de vardır.


2
@mertinan hiç duymadım diyemem, ama wikipedia "Mandal (veritabanı), (nispeten kısa ömürlü) bir dizin gibi bir sistem veri yapısı üzerinde kilit" diyor
Peter

2
Monitör belirli bir durumu bekler (örn. Kilit açıldığında), "izler".
Dzmitry Lazerka

25
Semafor bir muteks ile aynı değildir. Çok farklı kullanılırlar ve ayrıca farklı özelliklere sahiptirler (yani sahiplik ile ilgili). Örnek için bkz barrgroup.com/Embedded-Systems/How-To/RTOS-Mutex-Semaphore detaylar için
nanoquack

3
@nanoquack, yanıltıcı veya yanlış olduğunu düşünüyorsanız cevabımı düzenlemekten çekinmeyin.
Peter

3
Muteks ve semafor arasında daha net bir ayrım için, nanoquack'in bağlantısında, anahtar paragraf şudur : Bir semaforun doğru kullanımı bir görevden diğerine sinyal vermek içindir. aksine, semafor kullanan görevler ikisini birden değil sinyal ya da bekle'yi kullanır. "
ToolmakerSteve

117

Bu sözlerle ilgili birçok yanlış anlama var.

Bu, buraya mükemmel uyan önceki bir gönderiden ( https://stackoverflow.com/a/24582076/3163691 ):

1) Kritik Bölüm = Bir işlem içinde diğerlerinden yalnızca bir etkin iş parçacığının yürütülmesine izin vermek için kullanılan kullanıcı nesnesi . Seçilmeyen diğer evreler (bu nesneyi elde etmek için) uyku moduna alınır .

[İşlemler arası yetenek yok, çok ilkel bir nesne].

2) Mutex Semaphore (aka Mutex) = Farklı süreçler arasında diğerlerinden sadece bir aktif iş parçacığının yürütülmesine izin vermek için kullanılan çekirdek nesnesi . Seçilmeyen diğer evreler (bu nesneyi elde etmek için) uyku moduna alınır . Bu nesne, iş parçacığı sahipliğini, iş parçacığı sonlandırma bildirimini, özyinelemeyi (aynı iş parçacığından birden çok 'alma' çağrısı) ve 'öncelikli ters çevirme önleme'yi destekler.

[İşlemler arası kapasite, kullanımı çok güvenli, bir tür 'yüksek seviye' senkronizasyon nesnesi].

3) Sayım Semaforu (diğer adıyla Semaphore) = Bir grup aktif iş parçacığının diğerlerinden çalıştırılmasına izin vermek için kullanılan çekirdek nesnesi . Seçilmeyen diğer evreler (bu nesneyi elde etmek için) uyku moduna alınır .

Bununla birlikte, 'muteks' özniteliklerine sahip olmadığı için süreçler arası kullanım çok güvenli değildir: iş parçacığı sonlandırma bildirimi, özyineleme ?, 'öncelikli ters çevirme önleme'? Vb.).

4) Ve şimdi, 'spinlocks' hakkında konuşmak, önce bazı tanımlar:

Kritik Bölge = 2 veya daha fazla işlemle paylaşılan bir bellek bölgesi.

Lock = Değeri 'kritik bölgeye' girişe izin veren veya reddeden bir değişken. (Basit bir 'boole bayrağı' olarak uygulanabilir).

Meşgul bekleme = Bir değer görünene kadar bir değişkenin sürekli olarak test edilmesi.

En sonunda:

Spin-lock (diğer adıyla Spinlock) = Meşgul beklemeyi kullanan bir kilit . ( Kilidin alınması xchg veya benzeri atomik işlemlerle yapılır ).

[İplik uyku yok, çoğunlukla yalnızca çekirdek düzeyinde kullanılır. Kullanıcı seviyesi kodu için yetersiz].

Son bir yorum olarak, emin değilim ama yukarıdaki ilk 3 senkronizasyon nesnesinin (# 1, # 2 ve # 3) bu basit canavarı (# 4) uygulamalarının bir parçası olarak kullandıkları bazı büyük paralara bahse girebilirim.

İyi günler!.

Referanslar:

Li tarafından Caroline Yao (CMP Books) ile Gömülü Sistemler için Gerçek Zamanlı Kavramlar.

-Modern İşletim Sistemleri (3.) Andrew Tanenbaum (Pearson Education International).

-Windows Richter (Microsoft Programlama Serisi) tarafından Microsoft Windows (4.) için Programlama Uygulamaları.

Ayrıca, şuraya da bakabilirsiniz: https://stackoverflow.com/a/24586803/3163691


1
Aslında kritik bölüm bir çekirdek nesnesi değildir , bu nedenle süreçler arasında daha hafif ve senkronize edilemez.
Vladislavs Burakovs

2
@ Vladislavs Burakovs: Haklısın! Redaksiyonumu affedin. Tutarlılık uğruna düzelteceğim.
fante

Nanoquack başka yerde bahseder gibi muteks ve semafor arasında daha net bir ayrım için, bkz barrgroup.com/Embedded-Systems/How-To/RTOS-Mutex-Semaphore - Anahtar paragraf " Semafora doğru kullanımı bir işe sinyal içindir Muteks, koruduğu paylaşılan kaynağı kullanan her görev tarafından her zaman bu sırayla alınmalı ve serbest bırakılmalıdır. Aksine, semafor kullanan görevler ikisini birden değil sinyal ya da bekleme kullanır. "
ToolmakerSteve

[Verimsiz] spinlock üzerine inşa edilen diğer kilit mekanizmalarının: AFAIK sadece bazı atomik işlemlere ek olarak uyku kuyruklarına ihtiyaç duyar . Çekirdeğin içinde spinlock gerekli olduğunda bile , modern çözümler Vikipedi - Spinlock - Alternative - " .. bölümünde açıklandığı gibi etkisini en aza indirir ." Uyarlamalı muteks "adlı karma bir yaklaşım kullanın. şu anda çalışan bir iş parçacığı, ancak iş parçacığı şu anda çalışmıyorsa uyumak. (Sonuncusu her zaman tek işlemcili sistemlerde geçerlidir.) "
ToolmakerSteve

@ToolmakerSteve, 'uyku kuyruğuna' bir iş parçacığı kimliği 'eklemeye çalışırken' çarpışma 'sorunu için' spinlock 'olmadan bir' çözüm 'sağlamaya cesaret ediyorum. Her neyse, Wikipedia metni uygulamada bir spinlock'un kullanıldığı sonucuna varmıştır.
fante

27

Çoğu problem (i) sadece kilitler, (ii) sadece semaforlar, ... veya (iii) her ikisinin bir kombinasyonu kullanılarak çözülebilir! Bildiğiniz gibi, çok benzerler: her ikisi de yarış koşullarını önler , her ikisi de acquire()/ release()işlemleri vardır, her ikisi de sıfır veya daha fazla iş parçacığının engellenmesine / şüphelenilmesine neden olur ... Gerçekten, önemli fark sadece nasıl kilitlendiklerine ve kilidini açtıklarına dayanır .

  • Bir kilit (veya muteks ) iki duruma (0 veya 1) sahiptir. Ya edilebilir kilidi veya kilitli . Genellikle bir kerede yalnızca bir iş parçacığının kritik bir bölüme girmesini sağlamak için kullanılırlar.
  • Bir semaforun birçok durumu vardır (0, 1, 2, ...). Bu edilebilir kilitli (0 durumu) veya kilidi (3, 2, 1 belirtmektedir, ...). Bazı kaynakların birim sayısı belirli bir değere ulaştığında (veya bu değere geri sayma veya bu değere kadar sayma yoluyla) yalnızca bir iş parçacığının tam olarak kritik bir bölüme girmesini sağlamak için genellikle bir veya daha fazla semafor kullanılır ).

Her iki kilit / semafor için, acquire()ilkel 0 durumundayken çağrı yapmaya çalışmak , çağıran iş parçacığının askıya alınmasına neden olur. Kilitler için - kilit 1 durumundaki edinme girişimleri başarılı. Semaforlar için - {1, 2, 3, ...} durumlarında kilidi alma girişimleri başarılı olur.

Durum durumu 0'daki kilitler için , daha önce çağrılan aynı iş parçacığı varsa acquire(), şimdi sürüm çağırır, sürüm başarılı olur. Bir Eğer farklı iplik denedim - bu olur (ihmal genellikle girişimi veya bir hata atılır) ne olduğu uygulama / kütüphaneye aşağıda. Durum 0'daki semaforlar için, herhangi bir iş parçacığı bırakmayı çağırabilir ve başarılı olur (daha önce kullanılan hangi iş parçacığının semaforu 0 durumuna getirmek için aldığından bağımsız olarak).

Yukarıdaki tartışma itibaren biz kilitleri bir bir kavram var olduğunu görebilirsiniz sahibine semaforlar (herhangi bir iş parçacığı bir semaforda salınımını çağırabilir) bir sahibi yok oysa, (serbest bırakma sahibidir çağırabilir tek iplik).


Çok fazla karışıklığa neden olan şey, pratikte bu üst düzey tanımın birçok varyasyonu olmasıdır.

Dikkate alınması gereken önemli varyasyonlar :

  • acquire()/ release()Denen ne olmalı ? - [Büyük ölçüde değişir ]
  • Kilit / semaforunuz bekleyen konuları hatırlamak için bir "kuyruk" veya "küme" kullanıyor mu?
  • Kilidiniz / semaforunuz diğer işlemlerin konuları ile paylaşılabilir mi?
  • Kilidiniz "evrendi" mi? - [Genellikle evet].
  • Kilidiniz "engelliyor / engellemiyor" mu? - [Normalde engellememesi, engelleme kilitleri (diğer adıyla kilitler olarak da bilinir) meşgul beklemeye neden olur].
  • Operasyonların "atom" olmasını nasıl sağlıyorsunuz?

Bunlar kitabınıza / okutmanınıza / dilinize / kütüphanenize / ortamınıza bağlıdır.
İşte bazı dillerin bu ayrıntılara nasıl cevap verdiğini belirten hızlı bir tur.


C, C ++ ( pthreads )

  • Bir muteks üzerinden uygulanır pthread_mutex_t. Varsayılan olarak, diğer işlemlerle ( PTHREAD_PROCESS_PRIVATE) paylaşılamazlar , ancak mutekslerin pshared adlı bir özniteliği vardır . Ayarlandığında, muteks işlemler ( PTHREAD_PROCESS_SHARED) arasında paylaşılır .
  • Bir kilit bir muteks aynı şeydir.
  • Bir semafor üzerinden uygulanır sem_t. Mutekslere benzer şekilde, semaforlar birçok işlemin yüzdeleri arasında paylaşılabilir veya tek bir işlemin iş parçacıklarına özel tutulabilir. Bu, sağlanan pshared argümana bağlıdır sem_init.

python ( threading.py )

  • Bir lock ( threading.RLock) çoğunlukla C / C ++ pthread_mutex_ts ile aynıdır . Her ikisi de evre . Bu, bunların kilidini yalnızca onu kilitleyen aynı iplikle açabileceği anlamına gelir. O durumda sem_tsemaforlar, threading.Semaphoresemaforlar ve theading.Lockkilitleri evresel değildir - bu durumda için herhangi semaforda aşağı / kilit açma gerçekleştirebilir.
  • Bir mutex bir kilit (terim piton genellikle kullanılmamaktadır) ile aynıdır.
  • bir semafor ( threading.Semaphore) çoğunlukla ile aynıdır sem_t. Bununla birlikte sem_t, bir iş parçacığı kimlikleri kuyruğu, kilitli iken kilitlemeye çalışırken iş parçacıklarının engellenme sırasını hatırlamak için kullanılır. Bir iş parçacığı semaforun kilidini açtığında , kuyruktaki ilk iş parçacığı (varsa) yeni sahip olarak seçilir. İş parçacığı tanımlayıcısı kuyruktan alınır ve semafor yeniden kilitlenir. Bununla birlikte, threading.Semaphoresıra yerine bir küme kullanılır, böylece evrelerin engellenme sırası saklanmaz - kümedeki herhangi bir evre bir sonraki sahip olarak seçilebilir.

Java ( java.util.concurrent )

  • Bir lock ( java.util.concurrent.ReentrantLock) çoğunlukla C / C ++ ile aynıdır pthread_mutex_tve Python's threading.RLockda bir yeniden giriş kilidi uygular. JVM'nin aracı görevi görmesi nedeniyle işlemler arasında kilitleri paylaşmak daha zordur. Bir iş parçacığı, sahip olmadığı bir kilidi açmaya çalışırsa, a IllegalMonitorStateExceptionatılır.
  • Bir mutex bir kilit (terim Java sık kullanılmaz) ile aynıdır.
  • Bir semafor (java.util.concurrent.Semaphore ) daha çok aynıdır sem_tve threading.Semaphore. Java semaforları için yapıcı , bekleyen iş parçacıklarını saklamak için bir küme (false) veya kuyruk (true) kullanıp kullanılmayacağını denetleyen bir adalet boole parametresini kabul eder .

Teorik olarak semaforlar sıklıkla tartışılır, ancak pratikte semaforlar çok fazla kullanılmaz. Bir semafor yalnızca bir tamsayının durumunu tutar , bu nedenle çoğu zaman oldukça esnek değildir ve bir kerede birçoğuna ihtiyaç vardır - kodun anlaşılmasında zorluklara neden olur. Ayrıca, herhangi bir ipliğin bir semaforu serbest bırakabilmesi bazen istenmez. Bunun yerine, "koşul değişkenleri" ve "monitörler" gibi daha nesne yönelimli / üst düzey senkronizasyon ilkelleri / soyutlamaları kullanılır.


22

John Kopplin'in Multithreading Tutorial'a bir göz atın .

Konular Arasında Senkronizasyon bölümünde olay, kilit, muteks, semafor, bekleme süresi arasındaki farkları açıklar.

Bir muteks , aynı anda yalnızca bir iş parçacığına ait olabilir ve iş parçacıklarının paylaşılan bir kaynağa karşılıklı olarak özel erişimi koordine etmesini sağlar

Kritik bölüm nesneleri , mutex nesneleri tarafından sağlanana benzer senkronizasyon sağlar, ancak kritik bölüm nesneleri yalnızca tek bir işlemin iş parçacıkları tarafından kullanılabilir

Muteks ve kritik bölüm arasındaki diğer bir fark , kritik bölüm nesnesinin şu anda başka bir iş parçacığına ait olması durumunda mutex ile birlikte kullanılan EnterCriticalSection()süresiz olarak beklemeyi WaitForSingleObject(), bir zaman aşımını belirtmenize izin vermesidir.

Bir semafor , eşzamanlı olarak paylaşılan bir kaynağa erişen iş parçacığı sayısını sınırlandırarak sıfır ile maksimum değer arasında bir sayı tutar.


15

Örneklerle örtmeye çalışacağım:

Kilitle: Kullanacağınız örnek, lock(benzersiz anahtarları olması gereken) öğelerin eklendiği paylaşılan bir sözlük olabilir.
Kilit, bir iş parçacığının sözlükte olan öğeyi kontrol eden kod mekanizmasına girmemesini sağlarken, başka bir iş parçacığı (kritik bölümdeki) bu denetimi geçmiş ve öğeyi ekler. Başka bir iş parçacığı kilitli bir kod girmeye çalışırsa, nesne serbest bırakılana kadar bekler (engellenir).

private static readonly Object obj = new Object();

lock (obj) //after object is locked no thread can come in and insert item into dictionary on a different thread right before other thread passed the check...
{
    if (!sharedDict.ContainsKey(key))
    {
        sharedDict.Add(item);
    }
}

Semafor: Diyelim ki bir bağlantı havuzunuz var, o zaman tek bir iş parçacığı semaforun bağlantı kurmasını bekleyerek havuzdaki bir öğeyi ayırabilir. Daha sonra bağlantıyı kullanır ve iş yapıldığında semaforu serbest bırakarak bağlantıyı serbest bırakır.

Sevdiğim kod örneği @Patric tarafından verilen fedai biridir - işte gidiyor:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace TheNightclub
{
    public class Program
    {
        public static Semaphore Bouncer { get; set; }

        public static void Main(string[] args)
        {
            // Create the semaphore with 3 slots, where 3 are available.
            Bouncer = new Semaphore(3, 3);

            // Open the nightclub.
            OpenNightclub();
        }

        public static void OpenNightclub()
        {
            for (int i = 1; i <= 50; i++)
            {
                // Let each guest enter on an own thread.
                Thread thread = new Thread(new ParameterizedThreadStart(Guest));
                thread.Start(i);
            }
        }

        public static void Guest(object args)
        {
            // Wait to enter the nightclub (a semaphore to be released).
            Console.WriteLine("Guest {0} is waiting to entering nightclub.", args);
            Bouncer.WaitOne();          

            // Do some dancing.
            Console.WriteLine("Guest {0} is doing some dancing.", args);
            Thread.Sleep(500);

            // Let one guest out (release one semaphore).
            Console.WriteLine("Guest {0} is leaving the nightclub.", args);
            Bouncer.Release(1);
        }
    }
}

MutexSemaphore(1,1) Küresel olarak oldukça fazla ve sıklıkla kullanılır (aksi takdirde geniş çapta uygulama lockdaha uygundur). Küresel Mutexolarak erişilebilir bir listeden düğümü silerken global kullanılır ( düğümü silerken başka bir iş parçacığının bir şey yapmasını istediğiniz son şey). Edindiğiniz zaman Mutexfarklı iplik çalışır aynı elde etmek eğer Mutexo elde ettiği AYNI parçacığı kadar uyumaya konacaktır Mutexbültenleri o.

Küresel muteks yaratmaya iyi bir örnek @deepee

class SingleGlobalInstance : IDisposable
{
    public bool hasHandle = false;
    Mutex mutex;

    private void InitMutex()
    {
        string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
        string mutexId = string.Format("Global\\{{{0}}}", appGuid);
        mutex = new Mutex(false, mutexId);

        var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
        var securitySettings = new MutexSecurity();
        securitySettings.AddAccessRule(allowEveryoneRule);
        mutex.SetAccessControl(securitySettings);
    }

    public SingleGlobalInstance(int timeOut)
    {
        InitMutex();
        try
        {
            if(timeOut < 0)
                hasHandle = mutex.WaitOne(Timeout.Infinite, false);
            else
                hasHandle = mutex.WaitOne(timeOut, false);

            if (hasHandle == false)
                throw new TimeoutException("Timeout waiting for exclusive access on SingleInstance");
        }
        catch (AbandonedMutexException)
        {
            hasHandle = true;
        }
    }


    public void Dispose()
    {
        if (mutex != null)
        {
            if (hasHandle)
                mutex.ReleaseMutex();
            mutex.Dispose();
        }
    }
}

sonra gibi kullanın:

using (new SingleGlobalInstance(1000)) //1000ms timeout on global lock
{
    //Only 1 of these runs at a time
    GlobalNodeList.Remove(node)
}

Umarım bu size biraz zaman kazandırır.


8

Wikipedia, Semaforlar ve Muteksler arasındaki farklar konusunda harika bir bölüme sahiptir :

Muteks, aslında ikili bir semaforla aynı şeydir ve bazen aynı temel uygulamayı kullanır. Aralarındaki farklar:

Muteksler, muteksi kilitleyen süreç olan bir sahip kavramına sahiptir. Sadece muteksi kilitleyen işlem kilidini açabilir. Buna karşılık, bir semaforun sahiplik kavramı yoktur. Herhangi bir işlem semaforun kilidini açabilir.

Semaforların aksine, muteksler öncelikli ters çevirme güvenliği sağlar. Muteks mevcut sahibini bildiğinden, muteks üzerinde daha yüksek öncelikli bir görev beklemeye başladığında sahibin önceliğini yükseltmek mümkündür.

Muteksler ayrıca, muteksi tutan işlemin yanlışlıkla silinemediği silme güvenliği de sağlar. Semaforlar bunu sağlamaz.


5

Anladığım kadarıyla, bir muteksin yalnızca tek bir işlemde değil, birçok iş parçacığında kullanılabilirken, bir semafor birden fazla işlemde ve karşılık gelen iş parçacığı kümelerinde kullanılabilir.

Ayrıca, bir muteks ikili (kilitli veya kilidi açık) iken, bir semaforun sayma kavramı veya birden fazla kilitleme ve kilit açma isteği kuyruğu vardır.

Birisi açıklamamı doğrulayabilir mi? Linux bağlamında, özellikle 2.6.32 çekirdeğini kullanan Red Hat Enterprise Linux (RHEL) sürüm 6'da konuşuyorum.


3
Şimdi bu, farklı işletim sistemlerinde farklı olabilir, ancak pencerelerde bir Mutex, en azından .net Mutex nesnesi gibi birden fazla işlem tarafından kullanılabilir ..
Peter

2
stackoverflow.com/questions/9389730/… "Aynı işlemdeki veya diğer işlemlerdeki iplikler muteksleri paylaşabilir." bu yüzden hiçbir muteks sürece özgü olmamalıdır.
Peter

3

Örnek olarak bir Linux varyantında C programlama kullanmak temel bir durumdur.

Kilit:

• Genellikle kilitli veya kilitsiz çalışan çok basit bir ikili yapı

• İş parçacığı sahipliği, öncelik, sıralama vb. Kavramları yok.

• Genellikle ipliğin sürekli olarak kilitlerin kullanılabilirliğini kontrol ettiği bir dönüş kilidi.

• Genellikle atomik işlemlere dayanır, örn. Test ve set, karşılaştırma ve takas, getirme ve ekleme vb.

• Genellikle atomik işlem için donanım desteği gerektirir.

Dosya Kilitleri:

• Genellikle bir dosyaya birden çok işlem aracılığıyla erişimi koordine etmek için kullanılır.

• Birden çok işlem okuma kilidini tutabilir, ancak herhangi bir işlem yazma kilidini tuttuğunda başka hiçbir işlemin okuma veya yazma kilidi edinmesine izin verilmez.

• Örnek: sürü, fcntl vb.

Karşılıklı dışlama:

• Mutex işlev çağrıları genellikle çekirdek alanında çalışır ve sistem çağrılarıyla sonuçlanır.

• Mülkiyet kavramını kullanır. Sadece şu anda muteksi tutan iş parçacığı kilidini açabilir.

• Mutex özyinelemeli değildir (İstisna: PTHREAD_MUTEX_RECURSIVE).

• Genellikle Koşul Değişkenleriyle İlişkili olarak kullanılır ve örneğin pthread_cond_signal, pthread_cond_wait vb.

• Bazı UNIX sistemleri muteks'in birden çok işlem tarafından kullanılmasına izin verir, ancak bu tüm sistemlerde uygulanmayabilir.

Semafor:

• Bu, değerleri sıfırın altına düşmesine izin verilmeyen bir çekirdek tarafından korunan tamsayıdır.

• İşlemleri senkronize etmek için kullanılabilir.

• Semaforun değeri 1'den büyük bir değere ayarlanabilir; bu durumda değer genellikle kullanılabilir kaynak sayısını gösterir.

• Değeri 1 ve 0 ile sınırlanmış bir semafor ikili semafor olarak adlandırılır.


0

Supporting ownership, maximum number of processes share lockve maximum number of allowed processes/threads in critical sectiongenel adıyla eşzamanlı nesnenin adını / türünü belirleyen üç ana faktör vardır lock. Bu faktörlerin değeri ikili olduğu için (iki durumu vardır), bunları 3 * 8 gerçeğe benzer bir tabloda özetleyebiliriz.

  • X (Sahipliği destekler?): Hayır (0) / evet (1)
  • Y (# paylaşım süreçleri):> 1 (∞) / 1
  • Z (CA'daki # süreç / iş parçacığı):> 1 (∞) / 1

  X   Y   Z          Name
 --- --- --- ------------------------
  0   ∞   ∞   Semaphore              
  0   ∞   1   Binary Semaphore       
  0   1   ∞   SemaphoreSlim          
  0   1   1   Binary SemaphoreSlim(?)
  1   ∞   ∞   Recursive-Mutex(?)     
  1   ∞   1   Mutex                  
  1   1   ∞   N/A(?)                 
  1   1   1   Lock/Monitor           

Bu tabloyu düzenlemek veya genişletmekten çekinmeyin, düzenlenebilir olması için bir ascii tablosu olarak gönderdim :)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.