Récemment, j'ai essayé d'accéder à une zone de texte à partir d'un fil (autre que le fil d'interface utilisateur) et une exception a été levée. Il a dit quelque chose sur le "code n'étant pas thread-safe" et j'ai donc fini par écrire un délégué (un exemple de MSDN a aidé) et l'appeler à la place.
Mais même ainsi, je ne comprenais pas tout à fait pourquoi tout le code supplémentaire était nécessaire.
Mise à jour: vais-je rencontrer des problèmes graves si je vérifie
Controls.CheckForIllegalCrossThread..blah =true
multithreading
thread-safety
definition
Vivek Bernard
la source
la source
Race-Condition
Réponses:
Eric Lippert a un joli billet de blog intitulé Quelle est cette chose que vous appelez "thread safe"? sur la définition de la sécurité des threads telle que trouvée sur Wikipedia
3 choses importantes extraites des liens:
Vaut vraiment le détour!
la source
Dans le plus simple des termes, threadsafe signifie qu'il est sûr d'être accessible à partir de plusieurs threads. Lorsque vous utilisez plusieurs threads dans un programme et qu'ils essaient chacun d'accéder à une structure de données commune ou à un emplacement en mémoire, plusieurs problèmes peuvent survenir. Donc, vous ajoutez du code supplémentaire pour éviter ces mauvaises choses. Par exemple, si deux personnes écrivaient le même document en même temps, la deuxième personne à enregistrer écrasera le travail de la première personne. Pour sécuriser les threads, vous devez forcer la personne 2 à attendre que la personne 1 termine sa tâche avant de permettre à la personne 2 de modifier le document.
la source
Wikipedia a un article sur la sécurité des threads.
Cette page de définitions (vous devez sauter une annonce - désolé) la définit ainsi:
Un thread est un chemin d'exécution d'un programme. Un seul programme threadé n'aura qu'un seul thread et donc ce problème ne se pose pas. Pratiquement tous les programmes GUI ont plusieurs chemins d'exécution et donc des threads - il y en a au moins deux, un pour traiter l'affichage de l'interface graphique et gérer l'entrée de l'utilisateur, et au moins un autre pour effectuer réellement les opérations du programme.
Ceci est fait pour que l'interface utilisateur soit toujours réactive pendant que le programme fonctionne en déchargeant tout processus de longue durée sur tous les threads non-UI. Ces threads peuvent être créés une fois et exister pour la durée de vie du programme, ou simplement être créés lorsque cela est nécessaire et détruits lorsqu'ils sont terminés.
Comme ces threads devront souvent effectuer des actions communes - E / S de disque, sortie des résultats à l'écran, etc. - ces parties du code devront être écrites de manière à pouvoir gérer les appels à partir de plusieurs threads, souvent à le même temps. Cela impliquera des choses comme:
la source
Simplement, thread safe signifie qu'une méthode ou une instance de classe peut être utilisée par plusieurs threads en même temps sans aucun problème.
Considérez la méthode suivante:
Maintenant, le thread A et le thread B aimeraient tous deux exécuter AddOne (). mais A commence en premier et lit la valeur de myInt (0) dans tmp. Maintenant, pour une raison quelconque, le planificateur décide d'arrêter le thread A et de reporter l'exécution au thread B. Le thread B lit maintenant aussi la valeur de myInt (toujours 0) dans sa propre variable tmp. Thread B termine la méthode entière, donc à la fin myInt = 1. Et 1 est retourné. C'est maintenant au tour de Thread A de nouveau. Le fil A continue. Et ajoute 1 à tmp (tmp était 0 pour le thread A). Et puis enregistre cette valeur dans myInt. myInt est à nouveau 1.
Donc, dans ce cas, la méthode AddOne a été appelée deux fois, mais parce que la méthode n'a pas été implémentée de manière thread-safe, la valeur de myInt n'est pas 2, comme prévu, mais 1 car le deuxième thread a lu la variable myInt avant la fin du premier thread le mettre à jour.
La création de méthodes thread-safe est très difficile dans les cas non triviaux. Et il y a pas mal de techniques. En Java, vous pouvez marquer une méthode comme synchronisée, cela signifie qu'un seul thread peut exécuter cette méthode à un moment donné. Les autres threads attendent en ligne. Cela rend une méthode sûre pour les threads, mais s'il y a beaucoup de travail à faire dans une méthode, cela gaspille beaucoup d'espace. Une autre technique consiste à `` marquer seulement une petite partie d'une méthode comme synchronisée ''en créant un verrou ou un sémaphore et en verrouillant cette petite partie (généralement appelée section critique). Certaines méthodes sont même implémentées en tant que thread safe sans verrou, ce qui signifie qu'elles sont construites de telle manière que plusieurs threads peuvent les parcourir en même temps sans jamais causer de problèmes, cela peut être le cas lorsqu'une méthode uniquement exécute un appel atomique. Les appels atomiques sont des appels qui ne peuvent pas être interrompus et qui ne peuvent être effectués que par un thread à la fois.
la source
Dans le monde réel, l'exemple pour le profane est
Supposons que vous ayez un compte bancaire avec Internet et les services bancaires mobiles et que votre compte ne dispose que de 10 $. Vous avez effectué un transfert de solde vers un autre compte à l'aide de services bancaires mobiles, et entre-temps, vous avez effectué des achats en ligne en utilisant le même compte bancaire. Si ce compte bancaire n'est pas threadsafe, la banque vous permet d'effectuer deux transactions en même temps et la banque sera alors en faillite.
Threadsafe signifie que l'état d'un objet ne change pas si simultanément plusieurs threads tentent d'accéder à l'objet.
la source
Vous pouvez obtenir plus d'explications dans le livre "Java Concurrency in Practice":
la source
Un module est thread-safe s'il garantit qu'il peut conserver ses invariants face à une utilisation multi-thread et concurrente.
Ici, un module peut être une structure de données, une classe, un objet, une méthode / procédure ou une fonction. Morceau de code essentiellement limité et données associées.
La garantie peut potentiellement être limitée à certains environnements tels qu'une architecture de processeur spécifique, mais doit être valable pour ces environnements. S'il n'y a pas de délimitation explicite des environnements, alors cela signifie généralement que pour tous les environnements, le code peut être compilé et exécuté.
Les modules thread-unsafe peuvent fonctionner correctement sous une utilisation multithread et simultanée, mais cela est souvent plus dû à la chance et au hasard qu'à une conception soignée. Même si certains modules ne se cassent pas pour vous, ils peuvent se briser lorsqu'ils sont déplacés vers d'autres environnements.
Les bogues multi-threads sont souvent difficiles à déboguer. Certains d'entre eux ne se produisent qu'occasionnellement, tandis que d'autres se manifestent de manière agressive - cela aussi peut être spécifique à l'environnement. Ils peuvent se manifester par des résultats subtilement faux ou des blocages. Ils peuvent perturber les structures de données de manière imprévisible et provoquer l'apparition d'autres bogues apparemment impossibles dans d'autres parties éloignées du code. Cela peut être très spécifique à une application, il est donc difficile de donner une description générale.
la source
Sécurité des threads : un programme thread-safe protège ses données des erreurs de cohérence de la mémoire. Dans un programme hautement multithread, un programme thread-safe ne provoque aucun effet secondaire avec plusieurs opérations de lecture / écriture à partir de plusieurs threads sur les mêmes objets. Différents threads peuvent partager et modifier les données d'objet sans erreurs de cohérence.
Vous pouvez atteindre la sécurité des threads en utilisant l'API de concurrence avancée. Cette page de documentation fournit de bonnes constructions de programmation pour assurer la sécurité des threads.
Les objets de verrouillage prennent en charge les idiomes de verrouillage qui simplifient de nombreuses applications simultanées.
Les exécuteurs définissent une API de haut niveau pour le lancement et la gestion des threads. Les implémentations d'exécuteur fournies par java.util.concurrent fournissent une gestion de pool de threads adaptée aux applications à grande échelle.
Les collections simultanées facilitent la gestion de grandes collections de données et peuvent réduire considérablement le besoin de synchronisation.
Les variables atomiques ont des fonctionnalités qui minimisent la synchronisation et aident à éviter les erreurs de cohérence de la mémoire.
ThreadLocalRandom (dans JDK 7) fournit une génération efficace de nombres pseudo-aléatoires à partir de plusieurs threads.
Reportez-vous également aux packages java.util.concurrent et java.util.concurrent.atomic pour d'autres constructions de programmation.
la source
Vous travaillez clairement dans un environnement WinForms. Les contrôles WinForms présentent une affinité de thread, ce qui signifie que le thread dans lequel ils sont créés est le seul thread qui peut être utilisé pour y accéder et les mettre à jour. C'est pourquoi vous trouverez des exemples sur MSDN et ailleurs montrant comment réorganiser l'appel sur le thread principal.
La pratique normale de WinForms consiste à avoir un seul thread dédié à tout votre travail d'interface utilisateur.
la source
Je trouve le concept de http://en.wikipedia.org/wiki/Reentrancy_%28computing%29 est ce que je considère généralement comme un threading dangereux, c'est-à-dire lorsqu'une méthode a et repose sur un effet secondaire tel qu'une variable globale.
Par exemple, j'ai vu du code qui formait des nombres à virgule flottante en chaîne, si deux d'entre eux sont exécutés dans des threads différents, la valeur globale de decimalSeparator peut être définitivement changée en '.'
la source
Pour comprendre la sécurité des threads, lisez les sections ci-dessous :
la source