Historique de la question :
Le support du travail avec des threads est apparu dans Perl 5.005, mais en raison des particularités de la mise en œuvre du langage, il est longtemps resté expérimental et a été accompagné d'un grand nombre de bogues et de limitations. À partir de Perl 5.8, le module threads (et threads::shared) est devenu suffisamment stable pour des tâches sérieuses, mais le modèle de threads de Perl diffère fortement de nombreux autres langages de programmation : chaque thread obtient sa propre copie de toutes les variables, et seules les structures explicitement déclarées via threads::shared sont accessibles en partage.
Problème :
Les variables "standard" ne sont pas visibles entre les threads en raison de la sémantique de copy-on-write. Tenter de partager des données sans threads::shared entraîne une désynchronisation des états. Une utilisation incorrecte des verrous présente un risque de conditions de course, de blocage ou de modifications incohérentes.
Solution :
Pour partager des variables, déclarez des variables partagées via use threads::shared. Verrouillez l'accès aux données partagées à l'aide de lock, surtout si plusieurs threads lisent/écrivent simultanément. Pour gérer le cycle de vie des threads, utilisez les méthodes join/detach. Pour des structures complexes, déclarez chaque élément partagé séparément, car seul le "niveau supérieur" ne garantit pas la sécurité des threads.
Exemple de code :
use threads; use threads::shared; my $counter :shared = 0; my @threads; for (1..10) { push @threads, threads->create(sub { for (1..1000) { lock($counter); ++$counter; } }); } $_->join() for @threads; print "Counter: $counter ";
Caractéristiques clés :
Le :shared garantit-il la sécurité des threads sans verrou supplémentaire ?
Non. L'attribut :shared permet d'accéder à la variable entre les threads, mais les modifications (par exemple, ++ ou --) ne sont pas atomiques. Un verrou est nécessaire pour chaque section critique.
Peut-on partager entre les threads une structure complexe (tableau de hachages) avec une seule directive :shared ?
Non. Seul le « niveau supérieur » du tableau ou du hachage sera partagé. Chaque élément imbriqué doit également être partagé, sinon les structures internes ne seront pas visibles par d'autres threads.
Un thread peut-il tuer un autre thread par un appel à exit ?
Non. exit termine l'ensemble du processus, pas un thread spécifique. L'arrêt d'un thread se fait via exit à l'intérieur du thread ou est géré par la logique join/detach.
Deux threads augmentent simultanément $counter :shared sans verrou. Le résultat final est inférieur à prévu (problème typique de mise à jour perdue).
Avantages :
Inconvénients :
Mise en œuvre d'un verrou à chaque modification d'une variable partagée. Pour de grandes structures, verrouillage imbriqué élément par élément.
Avantages :
Inconvénients :