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 critiques ne peuvent pas être partagés entre les processus.

Les objets événement, mutex et sémaphore peuvent également être utilisés dans une application à processus unique, mais les objets de section critiques fournissent un mécanisme légèrement plus rapide et plus efficace pour la synchronisation d’exclusion mutuelle (une instruction de test et de jeu spécifique au processeur). Comme un objet mutex, un objet de section critique ne peut appartenir qu’à 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 dire si une section critique a été abandonnée.

À compter de Windows Server 2003 avec Service Pack 1 (SP1), les threads qui attendent une section critique n’acquièrent pas la section critique sur la base du premier arrivé, premier service. Cette modification améliore considérablement les performances de la plupart du code. Toutefois, certaines applications dépendent de l’ordre du premier entré et du premier sorti (FIFO) et peuvent s’exécuter 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 ayez un thread producteur et 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 l’autre thread. Le thread consommateur attend que le producteur signale son événement avant d’entrer dans la section critique, et le thread producteur attend que le thread consommateur signale son événement avant d’entrer dans la section critique. Une fois que chaque thread a quitté la section critique, il signale à son événement de libérer l’autre thread.

Windows Server 2003 et Windows XP : Les 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, il suffit de déclarer 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 acceptent 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’interblocage tout en attendant une section critique qu’il possède déjà. Pour libérer sa propriété, le thread doit appeler LeaveCriticalSection une fois pour chaque fois qu’il est entré dans la section critique. Il n’existe aucune garantie quant à l’ordre dans lequel les threads en attente acquièrent 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 est mis en veille. Sur les systèmes monoprocesseurs, le nombre de spins est ignoré et le nombre de spins 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 se libère pendant l’opération de spin, le thread appelant évite l’opération d’attente.

N’importe quel thread du processus peut utiliser la fonction DeleteCriticalSection pour libérer les ressources système allouées lors de l’initialisation de l’objet de section critique. 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 est détenu, 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.

Objets Mutex

Utilisation d’objets de section critique