Je t'ai juste rappelé que c'est faux: on peut aussi utiliser un spinlock même si c'est rarement plus efficace à cause du bouclage, en effet. Les spinlocks ont des inconvénients, et je ne les aime pas plus que toi.
Ça fait un bout de temps que je vous regarde vous étriper sur les mutex/spinlock.
Quelques remarques :
1) Conceptuellement, mutex et spinlock, c'est très semblable. Les spinlock peuvent être vus comme une implémentation particulière de mutex à base d'attente active. Si le processeur possède des instructions atomiques, il est possible d'implémenter les spinlock entièrement en espace utilisateur. Seul pb: risque d'occupation indue du processeur. Risque de deadlock également si les priorités 'hard' des deux flots d'exécution sont différentes.
2) Pour synchroniser des flots d'exécution parallèle (j'entends par là "gérés par l'ordonnanceur du noyau"), l'arbitrage du l'ordonnanceur du noyau est indispensable pour éviter le problème évoqué précédemment (attente active, risque de consommation du CPU pour rien, deadlock, ...)
3) Depuis les noyaux 2.6 (peut-être pas les premiers), Linux contient les 'futex'. Ils permettent de synchroniser des flots d'exécution parallèle en restant en espace utilisateur s'il n'y a pas de contention et en demandant l'arbitrage du noyau dans le cas contraire. A noter que ce mécanisme ne suppose pas que les flots partagent la même VM. La nouvelle libpthread (nptl) permet ainsi de faire de la synchro entre threads d'applications différentes grâce à des futex placés dans une zone de mémoire partagé (cf pthread_mutexattr_setpshared())
Enfin, une remarque générale. Les problèmes de synchro sont globalement les mêmes entre threads ou process avec mémoire partagée. L'intérêt des threads étant qu'il y a déjà beaucoup d'outils dispo (mutex, sémaphores, ...) qui utilisent les futex (crucial pour avoir de bonnes perf dans un maximum de cas).
Avec les process à mémoire partagée, il faudra réécrire ces outils (c'est peut-être déjà fait, mais je ne connais pas). En outre, le code de démarrage/arrêt est plus compliqué : il faut gérer des 'objets' extérieurs au processus, donc l'initialisation et la destruction à la terminaison est plus délicate. Pour les threads, l'initialisation se déroule naturellement au démarrage lorsque les threads ne sont pas encore créés, et la destruction est faite par l'OS à la destruction du processus.
Et pour finir, ne pas oublier qu'avec la mémoire partagée, rien ne certifie a priori qu'elle sera mappée au même endroit : cela oblige à manipuler des handle plutôt que des pointeurs, ce qui peut être source d'une indirection supplémentaire (et de complexification du code et des structures de données)
[^] # Re: mmap ANONYMOUS n'a aucun surcout
Posté par Vincent Danjean . En réponse à la dépêche PTT : un outil de trace pour la NPTL. Évalué à 2.
Ça fait un bout de temps que je vous regarde vous étriper sur les mutex/spinlock.
Quelques remarques :
1) Conceptuellement, mutex et spinlock, c'est très semblable. Les spinlock peuvent être vus comme une implémentation particulière de mutex à base d'attente active. Si le processeur possède des instructions atomiques, il est possible d'implémenter les spinlock entièrement en espace utilisateur. Seul pb: risque d'occupation indue du processeur. Risque de deadlock également si les priorités 'hard' des deux flots d'exécution sont différentes.
2) Pour synchroniser des flots d'exécution parallèle (j'entends par là "gérés par l'ordonnanceur du noyau"), l'arbitrage du l'ordonnanceur du noyau est indispensable pour éviter le problème évoqué précédemment (attente active, risque de consommation du CPU pour rien, deadlock, ...)
3) Depuis les noyaux 2.6 (peut-être pas les premiers), Linux contient les 'futex'. Ils permettent de synchroniser des flots d'exécution parallèle en restant en espace utilisateur s'il n'y a pas de contention et en demandant l'arbitrage du noyau dans le cas contraire. A noter que ce mécanisme ne suppose pas que les flots partagent la même VM. La nouvelle libpthread (nptl) permet ainsi de faire de la synchro entre threads d'applications différentes grâce à des futex placés dans une zone de mémoire partagé (cf pthread_mutexattr_setpshared())
Enfin, une remarque générale. Les problèmes de synchro sont globalement les mêmes entre threads ou process avec mémoire partagée. L'intérêt des threads étant qu'il y a déjà beaucoup d'outils dispo (mutex, sémaphores, ...) qui utilisent les futex (crucial pour avoir de bonnes perf dans un maximum de cas).
Avec les process à mémoire partagée, il faudra réécrire ces outils (c'est peut-être déjà fait, mais je ne connais pas). En outre, le code de démarrage/arrêt est plus compliqué : il faut gérer des 'objets' extérieurs au processus, donc l'initialisation et la destruction à la terminaison est plus délicate. Pour les threads, l'initialisation se déroule naturellement au démarrage lorsque les threads ne sont pas encore créés, et la destruction est faite par l'OS à la destruction du processus.
Et pour finir, ne pas oublier qu'avec la mémoire partagée, rien ne certifie a priori qu'elle sera mappée au même endroit : cela oblige à manipuler des handle plutôt que des pointeurs, ce qui peut être source d'une indirection supplémentaire (et de complexification du code et des structures de données)