Objets de section critique
Un objet de section critique fournit une synchronisation similaire à celle fournie par un objet mutex, sauf qu’une section critique ne peut être utilisée que par les threads d’un seul processus. Les objets de section critique ne peuvent pas être partagés entre les processus.
Les objets event, mutex et sémaphore peuvent également être utilisés dans une application à processus unique, mais les objets de section critique fournissent un mécanisme légèrement plus rapide et plus efficace pour la synchronisation d’exclusion mutuelle (un test spécifique au processeur et une instruction de définition). Comme un objet mutex, un objet de section critique peut être détenu par un seul thread à la fois, ce qui le rend utile pour protéger une ressource partagée contre l’accès simultané. Contrairement à un objet mutex, il n’existe aucun moyen de savoir si une section critique a été abandonnée.
À compter de Windows Server 2003 avec Service Pack 1 (SP1), les threads en attente sur une section critique n’acquièrent pas la section critique sur une base de première venue et de premier service. Cette modification augmente considérablement les performances pour la plupart du code. Toutefois, certaines applications dépendent de l’ordre du premier entré et du premier sorti (FIFO) et peuvent fonctionner mal ou pas du tout sur les versions actuelles de Windows (par exemple, les applications qui utilisent des sections critiques comme limiteur de débit). Pour vous assurer que votre code continue de fonctionner correctement, vous devrez peut-être ajouter un niveau de synchronisation supplémentaire. Par exemple, supposons que vous disposez d’un thread de producteur et d’un thread consommateur qui utilisent un objet de section critique pour synchroniser leur travail. Créez deux objets d’événement, un pour chaque thread à utiliser pour signaler qu’il est prêt pour que l’autre thread continue. Le thread consommateur attend que le producteur signale son événement avant d’entrer dans la section critique, et le thread de producteur attend que le thread consommateur signale son événement avant d’entrer dans la section critique. Une fois que chaque thread quitte la section critique, il signale son événement pour libérer l’autre thread.
Windows Server 2003 et Windows XP : threads qui attendent une section critique sont ajoutés à une file d’attente ; ils sont réveillés et acquièrent généralement la section critique dans l’ordre dans lequel ils ont été ajoutés à la file d’attente. Toutefois, si des threads sont ajoutés à cette file d’attente à un rythme suffisamment rapide, les performances peuvent être dégradées en raison du temps nécessaire pour réveiller chaque thread en attente.
Le processus est responsable de l’allocation de la mémoire utilisée par une section critique. En règle générale, cela se fait en déclarant simplement une variable de type CRITICAL_SECTION. Avant que les threads du processus puissent l’utiliser, initialisez la section critique à l’aide de la fonction InitializeCriticalSection ou InitializeCriticalSectionAndSpinCount.
Un thread utilise la fonction EnterCriticalSection ou TryEnterCriticalSection pour demander la propriété d’une section critique. Il utilise la fonction LeaveCriticalSection pour libérer la propriété d’une section critique. Si l’objet de section critique appartient actuellement à un autre thread, EnterCriticalSection attend indéfiniment la propriété. En revanche, lorsqu’un objet mutex est utilisé pour l’exclusion mutuelle, les fonctions d’attente accepter un intervalle de délai d’attente spécifié. La fonction TryEnterCriticalSection tente d’entrer une section critique sans bloquer le thread appelant.
Lorsqu’un thread possède une section critique, il peut effectuer des appels supplémentaires à EnterCriticalSection ou TryEnterCriticalSection sans bloquer son exécution. Cela empêche un thread de s’interblocer tout en attendant qu’une section critique qu’elle possède déjà. Pour libérer sa propriété, le thread doit appeler LeaveCriticalSection une fois pour chaque fois qu’il a entré la section critique. Il n’existe aucune garantie sur l’ordre dans lequel les threads en attente acquériront la propriété de la section critique.
Un thread utilise la fonction InitializeCriticalSectionAndSpinCount ou SetCriticalSectionSpinCount pour spécifier un nombre de spins pour l’objet de section critique. L’épinglage signifie que lorsqu’un thread tente d’acquérir une section critique verrouillée, le thread entre dans une boucle, vérifie si le verrou est libéré et si le verrou n’est pas libéré, le thread passe en veille. Sur les systèmes à processeur unique, le nombre de spins est ignoré et le nombre de tours de section critique est défini sur 0 (zéro). Sur les systèmes multiprocesseurs, si la section critique n’est pas disponible, le thread appelant tourne dwSpinCount fois avant d’effectuer une opération d’attente sur un sémaphore associé à la section critique. Si la section critique devient libre pendant l’opération de rotation, le thread appelant évite l’opération d’attente.
Tout thread du processus peut utiliser la fonction DeleteCriticalSection pour libérer les ressources système allouées lorsque l’objet de section critique est initialisé. Une fois cette fonction appelée, l’objet de section critique ne peut pas être utilisé pour la synchronisation.
Lorsqu’un objet de section critique appartient, les seuls autres threads affectés sont les threads qui attendent la propriété dans un appel à EnterCriticalSection. Les threads qui n’attendent pas sont libres de continuer à s’exécuter.
Rubriques connexes