2011-01-16 14 views
51

http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspxSemaforo - A che cosa serve il conteggio iniziale?

Per creare un semaforo, è necessario fornire un conteggio iniziale e il conteggio massimo. MSDN afferma che un conteggio iniziale è -

Il numero iniziale di richieste per il semaforo che può essere concesso contemporaneamente.

Mentre si afferma che il massimo conteggio è

Il numero massimo di richieste per la semaforo che può essere concesso contemporaneamente.

Posso capire che il conteggio massimo è il numero massimo di thread che possono accedere a una risorsa contemporaneamente. Ma a che serve il conteggio iniziale?

Se creo un semaforo con un conteggio iniziale di 0 e un conteggio massimo di 2, nessuno dei miei thread del threadpool è in grado di accedere alla risorsa. Se imposto il conteggio iniziale come 1 e il conteggio massimo come 2, solo il thread del thread thread può accedere alla risorsa. È solo quando imposto sia il conteggio iniziale che il conteggio massimo come 2, 2 thread sono in grado di accedere alla risorsa contemporaneamente. Quindi, sono davvero confuso riguardo al significato del conteggio iniziale?

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 
+2

Come mai non hai mai accettato la risposta di SVGreg? – john

risposta

1

In questo modo, quando il thread corrente crea il semaforo, potrebbe richiedere alcune risorse dall'inizio.

+0

Quindi, vuoi dire quando voglio che due thread di lavoro accedano alla risorsa, dovrei cambiare il conteggio iniziale? – Sandbox

+0

No. È il thread corrente che richiede un conteggio. Se non si desidera che il thread corrente richieda un pass di accesso 0 o utilizzi il sovraccarico con un parametro. –

45

Sì, quando il numero iniziale è impostato su 0 - tutti i thread saranno in attesa mentre si incrementa la proprietà "CurrentCount". Puoi farlo con Release() o Release (Int32).

di uscita (...) - incrementerà il contatore di semaforo

Wait (...) - verrà diminuito lo

non è possibile incrementare il contatore ("currentCount" proprietà) superiore al valore massimo contare che hai impostato in fase di inizializzazione.

Ad esempio:

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() 
+1

Il codice verrà presentato meglio nella risposta anziché come un commento. – ChrisF

+0

Grazie. Perché ho pensato a come evidenziare il codice. – SVGreg

+1

LOL è probabilmente la quinta volta che raggiungo la stessa risposta perché la documentazione del costruttore mi confonde sempre su quali valori impostare. Cheers – BlueStrat

4

Quante discussioni si vuole essere in grado di accedere a risorse in una volta? Imposta il tuo conteggio iniziale su quel numero. Se quel numero non aumenterà mai per tutta la durata del programma, imposta il numero massimo anche su quel numero. In questo modo, se si verifica un errore di programmazione nel modo in cui si rilascia la risorsa, il programma si bloccherà e ti farà sapere.

(Ci sono due costruttori: uno che richiede solo un valore iniziale, e uno che prende inoltre il conteggio max Usa a seconda del caso..)

1

Se si desidera che nessun thread deve accedere alla risorsa per qualche tempo , si passa il conteggio iniziale a 0 e quando si desidera concedere l'accesso a tutti loro subito dopo aver creato il semaforo, si passa il valore del conteggio iniziale uguale al conteggio massimo. Per esempio:

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 

Come citato in MSDN Documentation- "Un altro uso di ReleaseSemaphore è durante l'inizializzazione di un'applicazione.L'applicazione può creare un semaforo con un conteggio iniziale pari a zero. Ciò imposta lo stato del semaforo su non segnalato e blocca tutti i thread dall'accesso alla risorsa protetta. Quando l'applicazione termina la sua inizializzazione, utilizza ReleaseSemaphore per aumentare il numero al suo valore massimo, per consentire l'accesso normale alla risorsa protetta."

+0

Scusa, ti ho dato l'esempio in C++, anche se puoi chiarire il dubbio. – Abhineet

28

Così, sono davvero confuso circa il significato di conteggio iniziale?

Un punto importante che può aiutare è che Wait decrementa il conteggio del semaforo e Release l'incrementa.

initialCount è il numero di risorse accessi che saranno ammessi subito. O, in altre parole, è la n umber of times Wait può essere chiamato senza bloccare immediatamente dopo l'istanziazione del semaforo.

maximumCount è il conteggio più alto che il semaforo può ottenere. È il numero di volte che è possibile chiamare Release senza generare un'eccezione supponendo che il conteggio initialCount sia zero. Se initialCount è impostato sullo stesso valore di maximumCount, chiamare immediatamente Release immediatamente dopo che il semaforo è stato istanziato genererà un'eccezione.

+3

Questo è molto utile! Stavo pensando a Semaphores all'indietro, poiché in initialCount era il numero di risorse BLOCK iniziali, non il numero di risorse disponibili immediatamente. Grazie. –

+1

@PhilipTenn, concordo - la documentazione non è chiara al riguardo – BlueStrat

+0

Ho acconsentito, dovevano cambiare il nome della variabile o aggiornare i documenti – IronHide

0

Come MSDN spiega sotto la sezione Osservazioni:

Se initialCount è inferiore maximumCount, l'effetto è come se il thread corrente aveva chiamato WaitOne (maximumCount meno initialCount) volte lo stesso. Se non si desidera prenotare alcuna voce per il thread che crea il semaforo, utilizzare lo stesso numero per maximumCount e initialCount.

Quindi, se il conteggio iniziale è 0 e massimo è 2, è come se WaitOne è stata chiamata due volte dal thread principale per cui abbiamo raggiunto la capacità massima (conteggio semaforo è 0 ora) e nessun thread può entrare semaforo. Allo stesso modo Se il conteggio iniziale è 1 e il massimo è 2, WaitOnce è stato chiamato una sola volta e solo un thread può essere inserito prima di raggiungere nuovamente la capacità e così via.

Se 0 è utilizzato per il conteggio iniziale, è sempre possibile chiamare Release (2) per aumentare il conteggio del semaforo su max per consentire il numero massimo di thread per acquisire la risorsa.