Est-il possible de prouver la sécurité des fils?

9

Étant donné un programme composé de variables et d'instructions qui modifient ces variables, et une primitive de synchronisation (un moniteur, un mutex, un java synchronisé ou un verrou C #), est-il possible de prouver qu'un tel programme est thread-safe?

Existe-t-il même un modèle formel pour décrire des choses comme la sécurité des fils ou les conditions de course?

Emiswelt
la source
2
Oui, mais les langues du monde réel peuvent être pénibles car leur sémantique simultanée n'est pas toujours bien définie / fixe. De plus, tout n'est pas décidable dans tous les modèles. C'est un vaste domaine; google "Concurrency Theory" pour se faire une idée. En particulier, il existe une riche théorie impliquant les réseaux de Petri.
Raphael

Réponses:

9

Il est difficile de prouver qu'un programme est "thread-safe". Il est cependant possible de définir concrètement et formellement le terme «course aux données». Et il est possible de déterminer si une trace d'exécution d'une exécution spécifique d'un programme a ou non une course de données dans le temps proportionnelle à la taille de la trace. Ce type d'analyse remonte au moins à 1988: Barton P. Miller, Jong-Deok Choi, «A Mechanism for Efficient Debugging of Parallel Programs», Conf. sur Prog. Lang. Dsgn. et Impl. (PLDI-1988): 135-144 .

Étant donné la trace d'une exécution, nous définissons d'abord un ordre partiel qui se produit avant les événements dans la trace. Étant donné deux événements et b qui se produisent sur le même thread, alors a < b ou . (Les événements sur le même thread forment un ordre total donné par la sémantique séquentielle du langage de programmation.) Les événements de synchronisation (il peut s'agir d'acquisitions et de sorties de mutex, par exemple), donnent un inter-thread supplémentaire qui se produit avant l'ordre partiel. (Si le thread libère un mutex et que le thread acquiert ce mutex, nous disons que la libération a lieu avant l'acquisition.)unebune<bb<uneST

Puis, étant donné deux accès aux données (lecture ou écriture sur des variables qui ne sont pas des variables de synchronisation) et qui sont au même emplacement de mémoire, mais par des threads différents et où ou est une opération d'écriture, nous disons qu'il y a une donnée- course entre et si ni ni .unebunebunebune<bb<une

La norme C ++ 11 est un bon exemple. (La section appropriée est 1.10 dans les spécifications provisoires disponibles en ligne.) C ++ 11 fait la distinction entre les objets de synchronisation (mutex et variables déclarées avec un atomic<>type) et toutes les autres données. La spécification C ++ 11 indique que le programmeur peut raisonner sur les accès aux données sur une trace d'un programme multithread comme s'il était séquentiellement cohérent si les accès aux données sont tous sans course de données.

L'outil Helgrind (qui fait partie de Valgrind) effectue ce type de détection basée sur les données avant que ne le fassent plusieurs outils commerciaux (par exemple, Intel Inspector XE.) Les algorithmes des outils modernes sont basés sur la conservation d'horloges vectorielles associées à chaque thread et à la synchronisation. objet. Je pense que cette technique d'utilisation d'horloges vectorielles pour la détection de la race des données a été lancée par Michiel Ronsse; Koen De Bosschere: "RecPlay: un système d'enregistrement / relecture pratique entièrement intégré", ACM Trans. Comput. Syst. 17 (2): 133-152, 1999 .

Logique errante
la source
6

Du côté pratique, il existe un système de vérification VCC qui peut être utilisé pour prouver formellement la sécurité des threads des programmes C.

Ceci est une citation du site web:

VCC prend en charge la simultanéité - vous pouvez utiliser VCC pour vérifier les programmes qui utilisent la simultanéité à granularité grossière et à granularité fine. Vous pouvez même l'utiliser pour vérifier vos primitives de contrôle d'accès concurrentiel. La vérification d'une fonction garantit implicitement la sécurité de son thread dans tout environnement concurrent respectant les contrats sur ses fonctions et ses structures de données.

Anton Dergunov
la source
2
Comment ça marche? Quel est le modèle formel sous-jacent? Notez que l'OP ne demande pas (seulement) un outil!
Raphael
1

Il s'agit d'un domaine très difficile à assurer l'exactitude du programme en ce qui concerne l'exclusion des conditions de course, une sorte de "talon d'Achille" de traitement parallèle. La meilleure approche pour l'exactitude du programme est généralement d'éviter les primitives de bas niveau et de travailler avec des modèles de conception de plus haut niveau (par exemple à partir de bibliothèques) qui assurent la synchronisation des threads. Il existe un modèle CSP, communiquant des processus séquentiels par Hoare, qui a des preuves de justesse étant donné que les développeurs se limitent au "framework". Il a une certaine similitude conceptuelle et une origine / chevauchement chronologique avec les "tuyaux et filtres" Unix bien que nous n'ayons pas (encore?) Trouvé de lien direct entre les deux.

Deux autres cadres qui tentent d'améliorer la correction de la parallélisation par des modèles de conception, et qui ont la plupart des algorithmes / modèles de conception standard / connus à cet effet:

vzn
la source
1
Cela peut être un bon conseil (de programmation), mais cela ne répond pas du tout à la question (CS).
Raphael
1
?!? la critique n'est pas du tout spécifique
vzn