2010-10-19 4 views
0

J'ai deux sémaphores x (initialement à 1), et y (initialement à 0).Synchronisation de sémaphore

Mon code de fonction de fil est un peu comme ceci:

... 

wait(x); 
    //setting some vars 
signal(x); 

wait(y); 

... 

Je veux faire en sorte que les threads attendent sur y en ligne, par exemple. si le premier thread a terminé la section x -gardé en premier, il devrait attendre y d'abord, & ainsi de suite. Dans l'implémentation actuelle, un changement de contexte intervenant après signal(x); peut empêcher que cela se produise.

Existe-t-il un moyen de le faire, ou dois-je restructurer complètement le code pour éviter cette éventualité?

Répondre

1

Malheureusement, les sémaphores et tous les autres outils de verrouillage POSIX ne permettent pas de définir des priorités ou similaires pour réguler l'ordre dans lequel ils sont obtenus. (Ce n'est pas un bogue mais une fonctionnalité.-)

La manière la plus simple d'accomplir la tâche que vous souhaitez est de protéger une variable d'état par un pthread_mutex_t et un correspondant. Dans la variable d'état, vous pouvez implémenter un horodatage simple pour suivre l'ordre dans lequel les threads ont traversé la section protégée. Quelque chose comme

struct state { 
pthread_mutex_t mutex; 
pthread_cond_t cond; 
size_t seen_at_x; 
size_t seen_at_y; 
}; 
0

Si cela est important pour vous, vous devez en effet restructurer le code. À ma connaissance, il n'y a aucune garantie que, lorsqu'un sémaphore est signalé, les processus en attente soient éveillés dans l'ordre dans lequel ils ont commencé à attendre.

Idéalement, vos processus ne devraient pas se soucier de l'ordre dans lequel ils atteignent le point de synchronisation et dans quel ordre ils continuent le traitement.

0

Je ne sais pas si cela va fonctionner! il ne permet pas d'annuler un thread synch/asynch mais je ne sais pas si cela fonctionne pour le changement de contexte entre les threads. essayez de mettre:

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL) 

et après la dernière ligne lorsque vous avez terminé avec elle:

pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL)