2011-09-19 21 views
8

Nel man page sembra che anche se si inizializzare un semaforo per un valore di uno:Come inizializzare un semaforo binario in C

sem_init(&mySem, 0, 1); 

Si potrebbe ancora essere incrementato ad un valore superiore a 1 con più chiamate a

sem_post(&mySem); 

Ma in questo code example il commento sembra pensare in modo diverso:

sem_init(&mutex, 0, 1);  /* initialize mutex to 1 - binary semaphore */ 

È possibile inizializzare un semaforo strettamente binario in C?

Nota: la ragione per eseguire questa operazione invece di utilizzare un mutex in questo caso è che sem_post e sem_wait possono essere chiamati da diversi thread.

risposta

8

Se si desidera un semaforo strettamente binario su Linux, suggerisco di creare uno su mutex e variabili di condizione.

struct binary_semaphore { 
    pthread_mutex_t mutex; 
    pthread_cond_t cvar; 
    int v; 
}; 

void mysem_post(struct binary_semaphore *p) 
{ 
    pthread_mutex_lock(&p->mutex); 
    if (p->v == 1) 
     /* error */ 
    p->v += 1; 
    pthread_cond_signal(&p->cvar); 
    pthread_mutex_unlock(&p->mutex); 
} 

void mysem_wait(struct binar_semaphore *p) 
{ 
    pthread_mutex_lock(&p->mutex); 
    while (!p->v) 
     pthread_cond_wait(&p->cvar, &p->mutex); 
    p->v -= 1; 
    pthread_mutex_unlock(&p->mutex); 
} 
+0

Grazie mille! Avevo finito per fare più o meno quello. – austinmarton

+0

Qual è esattamente il punto del ciclo 'while' in' mysem_wait'? Una semplice istruzione 'if' non eseguirà il lavoro poiché' pthread_cond_wait' richiederà il mutex dopo essere stato segnalato e 'pthread_cond_signal' sbloccherà solo un singolo thread in attesa della condizione? –

+2

@BillDeRose: le variabili di condizione sono soggette a wakeups spuri e wakeup rubati. Devi ** usarli in un ciclo se vuoi verificare una condizione. –