2009-08-10 4 views
4

Windows fournit un certain nombre d'objets utiles pour synchroniser les threads, tels que les événements (avec SetEvent et WaitForSingleObject), les mutex et les sections critiques.Pourquoi les bibliothèques implémentent-elles leurs propres verrous de base sur Windows?

Personnellement, je les ai toujours utilisés, en particulier les sections critiques, car je suis à peu près certain qu'elles n'engendrent que très peu de frais généraux, à moins qu'elles ne soient déjà verrouillées. Cependant, en regardant un certain nombre de bibliothèques, telles que boost, les gens vont alors avoir beaucoup de mal à implémenter leurs propres verrous en utilisant les méthodes imbriquées sur Windows.

Je peux comprendre pourquoi les gens écriraient des files d'attente sans verrous et autres, puisque c'est un cas spécialisé, mais y a-t-il une raison pour que les gens choisissent d'implémenter leurs propres versions des objets de synchronisation de base?

Répondre

14

Les bibliothèques ne mettent pas en œuvre leurs propres verrous. C'est pratiquement impossible à faire sans le soutien du système d'exploitation. Ce qu'ils font fait simplement l'emballage des mécanismes de verrouillage fournis par le système d'exploitation.

Boost il le fait pour deux raisons:

  • Ils sont en mesure de fournir une API de verrouillage beaucoup mieux conçu, en tirant parti des fonctionnalités de C. L'API Windows est C seulement, et pas très bien conçu C, à cela.
  • Ils sont capables d'offrir un certain degré de portabilité. la même API Boost peut être utilisée si vous exécutez votre application sur une machine Linux ou sur Mac. L'API de Windows est évidemment propre à Windows.
  • Les mécanismes fournis par Windows ont un désavantage flagrant: ils exigent que vous incluiez windows.h, ce que vous pouvez vouloir éviter pour un grand nombre de raisons, en particulier son abus extrême de macro polluant l'espace de nom global.
+0

En regardant boost \ thread \ win32 \ basic_timed_mutex.hpp Je ne vois aucune utilisation des objets de threading win32, tout semble être fait avec les méthodes imbriquées, qui utilisent des instructions CPU spéciales de toute façon qui sont atomiques. –

+2

Les méthodes interbloquées sont également à la base de certains objets de synchronisation Win32, c'est tout ce dont vous avez vraiment besoin pour dire mutex ou select. – Blindy

+0

Les méthodes interverrouillées font partie de l'API Win32. Ils ne sont pas plus portables que les objets de synchronisation Win32 de haut niveau. – jalf

4

Une raison particulière à laquelle je peux penser est la portabilité. Les verrous Windows sont parfaits, mais ils ne sont pas portables sur d'autres plates-formes. Une bibliothèque qui souhaite être portable doit implémenter son propre verrou pour garantir la même sémantique sur toutes les plateformes.

+0

Donc, fondamentalement, le fait de dire que le code de Windows boost utilise les méthodes interlockées est fondamentalement conçu pour fonctionner de la même façon que pthreads d'autres plates-formes? –

+0

@Fire Lancer, Oui, je suis ** spéculer ** c'est le cas – JaredPar

1

L'écriture d'un code de verrouillage pour une bibliothèque est utile si cette bibliothèque est destinée à être multi-plateforme. Les utilisateurs de la bibliothèque peuvent utiliser la fonctionnalité de verrouillage de la bibliothèque sans se préoccuper de l'implémentation de la plateforme sous-jacente. En supposant que la bibliothèque a des versions pour toutes les plates-formes qui sont ciblées, c'est un peu moins de code qui doit être porté.

+0

JaredPar a posté la même réponse –

2
  1. Dans de nombreuses bibliothèques (aka Boost), vous devez écrire le code de la plate-forme corss. Donc, en utilisant WaitForSingleObject et SetEvent sont no-go. En outre, il existe des idiomes communs, comme Moniteurs, conditions que Win32 API manque, (mais il peut être implémenté en utilisant ces primitives de base)
  2. Certaines structures de données sans verrou comme compteur atomique sont très utiles; par exemple: boost::shared_ptr les utilise pour sécuriser les threads sans surcharge de la section critique, la plupart des compilateurs (pas msvc) utilisent des compteurs atomiques pour implémenter la copie-écriture-écriture sécurisée std::string.
  3. Certaines choses, comme les files d'attente, peuvent être mises en œuvre de manière très efficace sans risque de blocage des threads, ce qui peut améliorer considérablement la performance dans certaines applications.
2

Il peut parfois y avoir de bonnes raisons d'implémenter vos propres verrous qui n'utilisent pas les objets de synchronisation du système d'exploitation Windows. Mais le faire est un "bâton pointu."Il est facile de se mettre dans le pied

Voici un exemple: Si vous savez que vous exécutez le même nombre de threads que de contextes matériels, et si la latence de réveil de l'un de ces threads est en attente pour un verrou est très important pour vous, vous pouvez choisir un verrou spin complètement implémenté dans l'espace utilisateur Si le thread en attente est le seul thread tournant sur le verrou, la latence de transfert du verrou du thread qui le possède au thread en attente est juste la latence de déplacement de la ligne de cache vers le thread propriétaire et de retour vers le thread en attente - ordres de grandeur plus rapide que la latence de signalisation d'un thread avec un verrouillage du système d'exploitation dans les mêmes circonstances. vouloir le faire est assez étroit. Alors que vous commencez à avoir plus de threads logiciels que de threads matériels, vous le regretterez probablement. Dans ce scénario, vous pourriez dépenser des quanta entiers de planification de système d'exploitation ne faisant rien mais tournant sur votre serrure de rotation. Et, si vous vous souciez de la puissance, les spinlocks sont mauvais parce qu'ils empêchent le processeur de passer à un état de faible consommation d'énergie. Je ne suis pas sûr que j'achète l'argument de portabilité. Les bibliothèques portatives ont souvent une couche de portabilité du système d'exploitation qui résume les différentes API du système d'exploitation pour la synchronisation. Si vous traitez des verrous, pthread_mutex peut être rendu sémantiquement identique à Windows Mutex ou Critical Section sous une couche d'abstraction. Il y a quelques exceptions ici, mais pour la plupart des gens, c'est vrai. Si vous traitez des variables d'état Windows ou POSIX, eh bien, celles-ci sont plus difficiles à résumer. (Vista a introduit des variables de condition de type POSIX, mais peu de développeurs de logiciels Windows sont en mesure d'exiger Vista ...)

Questions connexes