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
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()
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.
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.)
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. "
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.
Auf diese Weise könnte der aktuelle Thread, wenn er das Semaphor erstellt, einige Ressourcen von Anfang an beanspruchen.
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.