web-dev-qa-db-de.com

Semaphore - Was ist die anfängliche Zählung?

http://msdn.Microsoft.com/de-de/library/system.threading.semaphoreslim.aspx

Um ein Semaphor zu erstellen, muss ich eine Anfangszählung und eine Höchstzahl angeben. MSDN gibt an, dass eine Anfangszählung - ist 

Die anfängliche Anzahl von Anforderungen für die Semaphor, der gewährt werden kann gleichzeitig.

Während es sagt, dass die maximale Anzahl ist 

Die maximale Anzahl von Anforderungen für die Semaphor, der gewährt werden kann gleichzeitig.

Ich kann verstehen, dass die maximale Anzahl die maximale Anzahl von Threads ist, die gleichzeitig auf eine Ressource zugreifen können. Aber was ist die anfängliche Zählung? 

Wenn ich ein Semaphor mit einem Anfangszähler von 0 und einem Höchstzähler von 2 erstelle, kann keiner meiner Threadpool-Threads auf die Ressource zugreifen. Wenn ich die Anfangszählung als 1 und die Höchstzahl als 2 festlege, kann nur ein Thread-Pool-Thread auf die Ressource zugreifen. Nur wenn ich sowohl die anfängliche Anzahl als auch die maximale Anzahl auf 2 eingestellt habe, können 2 Threads gleichzeitig auf die Ressource zugreifen. Also bin ich wirklich verwirrt über die Bedeutung der Anfangszählung.

SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0, 2); //all threadpool threads wait
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 2);//only one thread has access to the resource at a time
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2, 2);//two threadpool threads can access the resource concurrently
64
Sandbox

Ja, wenn die ursprüngliche Zahl auf 0 gesetzt ist, warten alle Threads, während Sie die Eigenschaft "CurrentCount" inkrementieren. Sie können dies mit Release () oder Release (Int32) tun.

Release (...) - erhöht den Semaphor-Zähler

Warten (...) - wird dekrementiert 

Sie können den Zähler ("CurrentCount" -Eigenschaft) nicht um den in der Initialisierung festgelegten Höchstwert erhöhen.

Zum Beispiel:

SemaphoreSlim^ s = gcnew SemaphoreSlim(0,2); //s->CurrentCount = 0
s->Release(2); //s->CurrentCount = 2
...

s->Wait(); //Ok. s->CurrentCount = 1
...

s->Wait(); //Ok. s->CurrentCount = 0
...

s->Wait(); //Will be blocked until any of the threads calls Release()
57
SVGreg

Also bin ich wirklich verwirrt über die Bedeutung der Anfangszählung.

Ein wichtiger Punkt, der hier helfen kann, ist, dass Wait die Semaphorenzahl verringert und Release sie erhöht.

initialCount ist die Anzahl der Ressourcenzugriffe, die sofort erlaubt werden. Oder anders ausgedrückt, es ist die Anzahl von Malen, die Wait aufgerufen werden kann, ohne unmittelbar nach dem Instanziieren des Semaphors blockiert zu werden.

maximumCount ist die höchste Anzahl, die das Semaphor erhalten kann. Dies ist die Anzahl, mit der Release aufgerufen werden kann, ohne eine Ausnahme auszulösen, wenn initialCount count null ist. Wenn für initialCount derselbe Wert wie für maximumCount festgelegt ist, wird beim Aufruf von Release unmittelbar nach der Instanziierung des Semaphors eine Ausnahme ausgelöst.

44
Brian Gideon

Wie viele Threads möchten Sie gleichzeitig auf die Ressource zugreifen können? Stellen Sie Ihre Anfangszählung auf diese Nummer ein. Wenn sich diese Zahl während der gesamten Programmdauer nicht erhöhen wird, setzen Sie auch Ihre maximale Anzahl auf diese Zahl. Wenn Sie bei der Freigabe der Ressource einen Programmierfehler haben, stürzt das Programm ab und informiert Sie darüber.

(Es gibt zwei Konstruktoren: einen, der nur einen Anfangswert enthält, und einen, der zusätzlich die maximale Anzahl berücksichtigt. Verwenden Sie den geeigneten Wert.)

5
Karmastan

Wenn Sie möchten, dass kein Thread längere Zeit auf Ihre Ressource zugreifen soll, übergeben Sie die Anfangszählung als 0 und wenn Sie den Zugriff auf alle von ihnen direkt nach dem Erstellen des Semaphors gewähren möchten, übergeben Sie den Wert der Anfangszählung gleich der maximalen Anzahl . Zum Beispiel:

hSemaphore = CreateSemaphoreA(NULL, 0, MAX_COUNT, NULL) ;

//Do something here
//No threads can access your resource

ReleaseSemaphore(hSemaphore, MAX_COUNT, 0) ;

//All threads can access the resource now

Wie in der MSDN-Dokumentation zitiert: "Eine weitere Verwendung von ReleaseSemaphore ist die Initialisierung einer Anwendung. Die Anwendung kann ein Semaphor mit einem Anfangszähler von Null erstellen. Dadurch wird der Status des Semaphors auf Nicht-Signalisiert gesetzt und der Zugriff aller Threads auf die geschützte Ressource wird blockiert beendet die Initialisierung und verwendet ReleaseSemaphore, um die Anzahl auf den Maximalwert zu erhöhen, um normalen Zugriff auf die geschützte Ressource zu ermöglichen. "

1
Abhineet

Semaphoren können verwendet werden, um einen Pool von Ressourcen zu schützen . Wir verwenden Ressourcenpools, um Dinge wiederzuverwenden, die - teuer sind - wie Datenbankverbindungen. 

Die anfängliche Zählung bezieht sich also auf die Anzahl verfügbarer Ressourcen im Pool beim Start eines Prozesses. Wenn Sie die initialCount im Code lesen, sollten Sie darüber nachdenken, wie viel Aufwand Sie im Vorfeld investieren, um diesen Ressourcenpool zu erstellen. 

Ich bin wirklich verwirrt über die Bedeutung der Anfangszählung.

Initial count = Upfront cost

Abhängig vom Nutzungsprofil Ihrer Anwendung kann dieser Wert die Leistung Ihrer Anwendung erheblich beeinträchtigen. Es ist nicht irgendeine willkürliche Zahl. 

Sie sollten sorgfältig darüber nachdenken, was Sie erstellen, wie teuer sie sind und wie viele Sie sofort benötigen. Sie sollten buchstäblich in der Lage sein, den optimalen Wert für diesen Parameter darzustellen, und sollten sich überlegen, ihn konfigurierbar zu machen, damit Sie die Leistung des Prozesses an den Zeitpunkt anpassen können, zu dem er ausgeführt wird.

1
rism

Auf diese Weise könnte der aktuelle Thread, wenn er das Semaphor erstellt, einige Ressourcen von Anfang an beanspruchen.

1
Erno de Weerd

Wie MSDN erklärt es im Abschnitt "Bemerkungen":

Wenn initialCount kleiner als maximumCount ist, ist der Effekt derselbe, als hätte der aktuelle Thread WaitOne-Zeiten (maximumCount minus initialCount) aufgerufen. Wenn Sie keine Einträge für den Thread reservieren möchten, der das Semaphor erstellt, verwenden Sie dieselbe Anzahl für maximumCount und initialCount.

Wenn also der Anfangszähler 0 und der Höchstwert 2 ist, ist es so, als ob WaitOne zweimal vom Hauptthread aufgerufen wurde, so dass wir die Kapazität erreicht haben (Semaphor Count ist jetzt 0) und kein Thread kann den Semaphor betreten. In ähnlicher Weise Wenn der Anfangszähler 1 und der Maximalwert 2 ist, wurde WaitOnce einmal aufgerufen, und nur ein Thread kann eintreten, bevor die Kapazität wieder erreicht wird und so weiter. 

Wenn für die Anfangszählung 0 verwendet wird, können Sie immer Release (2) aufrufen, um die Semaphorenzahl auf max zu erhöhen, damit die maximale Anzahl von Threads die Ressource abrufen kann. 

0
Irfan