Les sémaphores permettent de synchroniser l'accès au serveur en bloquant les clients désirant l'utiliser. Il faut toutefois remarquer qu'un client peut accéder un serveur sans utiliser ce mode de synchronisation. Cela peut être utile pour communiquer avec un serveur exécutant une tache en arrière plan (voir plus loin sous "communication asynchrone"), mais dans la plupart des cas les accès asynchrones généreront des situations illégales difficile à contrôler ou à identifier.
La synchronisation utilise 3 sémaphores que l'on appelle SEM0
, SEM1
et SEM2
. Ils ont les fonctions suivantes:
SEM0
permet de gérer l'accès au serveur. Il est initialisé à 1 par le serveur, indiquant par là que le serveur est libre. Chaque client voulant accéder le serveur doit commencer par décrémenter ce sémaphore avant d'effectuer une quelconque opération sur le bloc de communication ou sur les autres sémaphores. Si le serveur est occupé, le client et mis en attente et NCNT0
est incrémenté d'une unité.
Selon le mode de synchronisation, en fin de travail, c'est le serveur ou le client qui incrémente SEM0
pour libérer l'accès au serveur pour le client suivant.
SEM1
bloque le serveur tant que le bloc de communication ne contient rien de valide. Il est initialisé à zéro par le serveur qui se met tout de suite en attente par une décrémentation (dans ce cas NCNT1=1
). C'est le client qui incrémente ce sémaphore lorsqu'il a obtenu l'accès au serveur et remplis le bloc de communication.
Le serveur se remet en attente automatiquement en décrémentant SEM1
en fin de travail.
SEM2
est utilisé comme un flag, il indique si le serveur exécute une commande. Lorsqu'il vaut zéro, le serveur ne travaille pas, lorsqu'il vaut 1, il travaille. C'est toujours le client qui le pose à 1 avant d'ordonner l'exécution d'une commande au serveur en incrémentant le SEM1
. C'est le serveur qui le pose à zéro à la fin d'une exécution. Si le client veut attendre la fin d'une exécution, il se met en attente de valeur zéro sur ce sémaphore (dans ce cas ZCNT2=1
).
Ce sémaphore est utilisé lors des opérations d'initialisation d'un serveur où un serveur peut savoir s'il a été tué durant l'exécution d'une commande (SEM2=1
) et ainsi le signaler au client qui peut être toujours en attente.