L’implémentation du thread fprintf () par MSVCRT est-elle sûre?

Il semble que l’implémentation de fprintf () par la glibc est thread-safe , mais en est-il de même pour le CRT de Microsoft?

Par thread-safe, je ne veux pas dire juste planter, mais aussi que si plusieurs threads (dans le même processus) appellent fprintf() , les textes ne seront pas mélangés.

C’est-à-dire, par exemple, si le thread A appelle fprintf(stdout, "aaaa"); et le thread B appelle fprintf(stdout, "bbbb"); il est garanti de ne pas mélanger pour devenir aabbaabb .

Y a-t-il une telle garantie?

Oui. Dans les bibliothèques d’exécution multithread, chaque stream est associé à un verrou. Ce verrou est acquis au début de tout appel à une fonction printf et n’est libéré qu’avant le retour de la fonction printf.

Ce comportement est requirejs par C11 (il n’y avait pas de concept de “threads” dans la norme C jusqu’à C11). C11 §7.21.2 / 7-8 stipule:

Chaque stream est associé à un verrou utilisé pour empêcher les courses de données lorsque plusieurs threads d’exécution accèdent à un stream et pour restreindre l’entrelacement des opérations de stream effectuées par plusieurs threads. Un seul thread peut tenir ce verrou à la fois. Le verrou est réentrant: un seul thread peut tenir le verrou plusieurs fois à un moment donné.

Toutes les fonctions qui lisent, écrivent, positionnent ou interrogent la position d’un stream verrouillent celui-ci avant d’y accéder. Ils libèrent le verrou associé au stream une fois l’access terminé.

Visual C ++ ne prend pas complètement en charge C11, mais il est conforme à cette exigence. Quelques autres commentaires spécifiques à Visual C ++:

Tant que vous ne définissez pas _CRT_DISABLE_PERFCRIT_LOCKS (qui ne fonctionne qu’avec les bibliothèques d’exécution liées statiquement, libcmt.lib et friends) ou que vous n’utilisez pas les fonctions suffixées _nolock , la plupart des opérations effectuées sur un seul stream sont atomiques.

Si vous avez besoin d’atomicité sur plusieurs opérations d’un stream, vous pouvez acquérir le verrou d’un fichier vous-même en acquérant et en libérant le verrou vous-même à l’aide de _lock_file et _unlock_file .