Semaphore ve SemaphoreSlim arasında nasıl seçim yaparım?


109

Genel arayüzleri benzer görünüyor. Dokümantasyon SemaphoreSlim hafif bir alternatiftir ve Windows Çekirdek semaforları kullanmayan devletler. Bu kaynak SemaphoreSlim'in çok daha hızlı olduğunu belirtir. SemaphoreSlim hangi durumlarda Semafor üzerinde daha mantıklıdır ve bunun tersi de geçerlidir?


1
Semafor işi her zaman işletim sistemine aktarır. Bu, semaforun güçlü bir şekilde tartışılmaması durumunda onu nispeten pahalı hale getirir, çekirdek çağrısı kolayca 400 nanosaniye maliyetlidir. İnce iyilik önce bunu paylaşılan bir değişkenle ucuza yapmaya çalışır, yalnızca işe yaramadığında işletim sistemine çağrı yapar. Semaforun birden çok işlem tarafından paylaşılması gereken köşe durumu dışında her zaman ucuzluğu seviyorsunuz.
Hans Passant

Yanıtlar:


64

Bir fark, SemaphoreSlimsistem genelinde olabilen adlandırılmış semaforlara izin vermemesidir. Bu, bir SemaphoreSlim'in işlemler arası senkronizasyon için kullanılamayacağı anlamına gelir.

MSDN belgeleri ayrıca SemSlim'in "bekleme sürelerinin çok kısa olması beklendiğinde" kullanılması gerektiğini belirtir. Bu genellikle, ince versiyonun çoğu takas için daha hafif olduğu fikrini iyi bir şekilde birleştirir.


66
Keşke MS, bekleme süreleri "çok kısa" olmadığında ne olacağı hakkında bir şeyler yazsaydı.
John Reynolds

79
... ya da "çok kısa" ne anlama geliyor
Richard Szalay

9
Sisteme bağlı olarak, bir WaitOne veya Release yapmak için Semaphore için 1 mikrosaniye ve SemaphoreSlim için 1/4 mikrosaniye ["Özetle C # 5.0" sayfa. 890] Yani belki de çok kısa bekleme süreleriyle kastettikleri budur?
David Sherret

2
@dhsto İyi referans! Ancak, bağlantılı makalenin "paylaşılan kaynağa erişmek için bekleme sürelerinin çok kısa olduğu" anlamına geldiğini tahmin ediyorum - yani kaynak, semafor kodunun kendisi için bekleme süreleri anlamına gelmek yerine, uzun süre özel kullanımda kalmayacak mı? Semafor kodu, kaynağın ne kadar süreyle kilitli kaldığına bakılmaksızın her zaman çalışacaktır.
culix

4
@culix Semaphore ve SemaphoreSlim için kaynağa baktığımda, SemaphoreSlim'in yalnızca "çok kısa" beklemeler için kullanılması gerektiğinin ana sebebinin bir döndürme bekleme kullanması olduğundan şüpheleniyorum. Bu daha duyarlıdır, ancak çok fazla CPU tüketir ve anlık yanıtların daha az önemli olduğu daha uzun bekleme süreleri için israf olur. Semafor bunun yerine iş parçacığını engeller.
r2_118

17

MSDN belgeleri farkı açıklar.

Bir cümleyle:

  • SemaphoreSlim sınıfı, bekleme sürelerinin çok kısa olması beklendiğinde tek bir işlem içinde beklemek için kullanılabilen hafif, hızlı bir semaforu temsil eder.

1
Buna eklemek için, uygulamanızın bilgisayarınızda söz konusu Semafora erişmesi gereken tek işlem olduğu her durumda SemaphoreSlim'i kullanın.
Austin Salgat

2
@Salgat Bunu neden yaptın? Diğer yanıtlarda da belirtildiği gibi SemaphoreSlimSpinWait kullanılarak gerçekleştirilir, bu nedenle çok beklerseniz, çok fazla CPU zamanı harcarsınız. İşleminiz bilgisayardaki tek işlemse bu iyi bir fikir değildir.
M.Stramm

MSDN belgelerinden, "SemaphoreSlim sınıfı, tek bir uygulama içinde senkronizasyon için önerilen semafordur." Özel durumlar dışında, o semaforu yalnızca bir işlem kullanıyorsa, varsayılan olarak SemaphoreSlim'i kullanmalısınız. Herhangi bir eşzamanlı veri türü için genellikle özel istisnalar vardır, bu söylemeye gerek bile yoktur.
Austin Salgat

17

SemaphoreSlim, SpinWait ve Monitor'e dayalıdır, bu nedenle kilidi elde etmeyi bekleyen iş parçacığı, başka bir iş parçacığına teslim olmadan önce kilidi elde etme umuduyla bir süre CPU döngülerini yakıyor. Bu olmazsa, iş parçacıkları sistemlerin bağlamı değiştirmesine izin verir ve işletim sistemi bu iş parçacığını yeniden programladığında (bazı CPU döngülerini yakarak) tekrar dener. Uzun beklemelerde bu model önemli miktarda CPU döngüsünden geçebilir. Bu nedenle, bu tür bir uygulama için en iyi durum senaryosu, çoğu zaman bekleme süresinin olmadığı ve kilidi neredeyse anında edinebileceğiniz zamandır.

Semafor, işletim sistemi çekirdeğindeki uygulamaya dayanır, bu nedenle kilidi her aldığınızda, oldukça fazla CPU döngüsü harcarsınız, ancak bundan sonra iş parçacığı, kilidi açmak için gerektiği kadar uyur.


12

"Kısa süreler" tartışmasıyla ilgili olarak:

En azından SemaphoreSlim MSDN belgeleri şunu belirtir:

SemaphoreSlim sınıfı, tek bir uygulama içinde senkronizasyon için önerilen semafordur.

Açıklamalar bölümünde. Aynı bölüm ayrıca Semaphore ve SemaphoreSlim arasındaki temel farkı anlatır:

SemaphoreSlim, Windows çekirdek semaforlarını kullanmayan Semaphore sınıfına hafif bir alternatiftir. Semaphore sınıfının aksine, SemaphoreSlim sınıfı adlandırılmış sistem semaforlarını desteklemez. Bunu yalnızca yerel bir semafor olarak kullanabilirsiniz.


1
Diğer ayrıntılar: [SemaphoreSlim and other locks] use busy spinning for brief periods before they put the thread into a true Wait state. When wait times are expected to be very short, spinning is far less computationally expensive than waiting, which involves an expensive kernel transition: dotnet.github.io/docs/essentials/collections/...
Marco Sulla

0

Buradaki kaynak koduna baktım ve şunu buldum:

  1. Hem Semaphore hem de SemaphoreSlim, Win32 yerel tutamacını dahili olarak kullanan WaitHandle'dan türemiştir. Bu yüzden her ikisini de Dispose () yapmanız gerekiyor. Dolayısıyla, Slim'in hafif olduğu fikri şüphelidir.

  2. SemaphoreSlim, SpinWait'i dahili olarak kullanırken, Semaphore kullanmaz. Bu bana, beklemenin uzun sürmesinin beklendiği durumlarda, Semafor'un en azından CPU'nuzu boğmaması açısından daha iyi yapması gerektiğini söylüyor.


2
SemaphoreSlim WaitHandle'dan türetilmemiştir. Aslında tek bir amaç ile oluşturulmuştur - işlemleri tek bir süreç içinde senkronize etmeniz gereken görevlerde çekirdek alanı ilkel olan WaitHandle'dan türetmeyi ortadan kaldırmak.
Igor V Savchenko
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.