J'ai une classe avec une propriété Bool Devrais-je me soucier de sérialiser l'accès à cette propriété code> activé code> à l'aide de quelque chose comme activée code>, utilisée par une boucle sur un autre fil pour voir si elle devrait s'arrêter ou non. L'idée est qu'un thread différent puisse définir cette propriété sur FALSE et arrêter l'autre thread de fonctionner proprement. P>
la question h2>
verrouillage (LockObject) {...} code> ou est-ce sûr sans? p>
9 Réponses :
Les lectures de type primitives sont atomiques à condition qu'elles s'adaptent à une lecture de la CPU. Ainsi, une lecture de type primitif de 32 bits est atomique sur un processeur 32 bits, tandis qu'une lecture de type 64 bits n'est pas. Cependant, à moins que ce ne soit aussi volatile code> votre autre thread peut ne pas voir les modifications dues à la mise en cache. p>
Ce n'est pas entièrement vrai. Les lectures / écrit ne sont garantis que d'être atomiques si la taille de la valeur est inférieure ou égale à la buté de la CPU. Par conséquent, lion / écrit des INT64 sur une machine 32 bits ne sera pas atomique.
@Kent: Je suis d'accord, c'est pourquoi j'ai ajouté plus d'informations, mais peut-être ma mise à jour et votre commentaire se sont croisés. Est-ce toujours pas clair?
Eh bien, j'ai ajouté un peu de détail quand même. J'espère que c'est mieux.
Cela dépend également de l'alignement de la mémoire. Si une valeur de 32 bits se trouve être stockée dans deux emplacements de mémoire consécutive sur une machine 32 bits, on lit et écrivez ne sera pas atomique.
L'autre fil verrait le changement si c'est sur le même processeur, mais certainement pas si c'est sur un processeur différent. Volatile fonctionnera très bien.
@Mehmet: correct, mais je crois que le compilateur prend en charge cela.
Le CLR garantit toutes les variables gérés sont un mot aligné. Si vous découlez avec des pointeurs et des décalages explicites, tous les paris sont éteints.
Je pense que vous n'avez besoin que de marquer la variable booléenne comme volatile code>. Cela garantira que le fil que vous souhaitez arrêter d'exécuter voit toujours la valeur la plus mise à jour de ce booléen. P>
Si un thread Lisez la valeur et un autre thread Ecrivez la valeur, il est sécuritaire mais faites attention à déclarer la propriété compatible avec le mot clé volatil pour être sûr que la valeur sera synchronisée à tous les processeurs si vous exécutez. avec un PC Dualcore. P>
Si vous n'utilisez pas volatile ou enfermer le booléen, il fonctionnera x86. Cela ne fonctionne peut-être pas sur l'ITANIUM CPUS d'Intel (IA64). Voici Un bon codeProject KB Article qui explique tout. P>
Si vous n'utilisez pas volatile ou verrouillez-le, mais seulement sur un seul processeur. Plusieurs CPU et vos problèmes.
@Simon Hughes. Ce n'est pas ce que dit l'article, ou autre chose que j'ai jamais lu sur la question. Avez-vous une documentation qui montre cela?
Comme d'autres déjà indiqués correctement, sans faire la variable La partie pertinente de la spécification de langue C # ( < Strong> 10.4.3 Champs volatils forts> ) Supplément States: P>
Pour les champs volatils, cette réorganisation
Les optimisations sont restreintes: p>
Ces restrictions garantissent que tous
Les threads observent des écritures volatiles
effectué par tout autre fil dans le
ordre dans lequel ils ont été effectués. UNE
La mise en œuvre conforme n'est pas
nécessaire pour fournir un total unique
Commande d'écritures volatiles comme on le voit
de tous les fils d'exécution. le
Le type de champ volatil doit être un
des éléments suivants: p>
volatile code> peut être utilisé (ou un verrouillage
code> sur la variable) pour accéder à la valeur d'une variable de manière sécurisée. p>
volatile code> Le compilateur peut appliquer des techniques d'optimisation qui réorientant des instructions pouvant entraîner des résultats inattendus et imprévisibles. p>
octet code>,
Sbyte code>,
court code>,
ushort code>,
int code>,
uint code>,
char code>,
float code> ou
bool code>. li>
Enum code> -Type ayant un type de base d'octet, Sbyte, Short, Ushort,
int, ou uint. li>
ul>
blockQuote>
Si vous ne le marquez pas comme volatilité, il fonctionnera sur des ordinateurs de processeurs unique (en raison de l'atomicité 32 bits), mais pas de PC avec plusieurs processeurs, car il tient la valeur dans son cache sur la matrice et ne récupérerait pas le très Dernière valeur, par conséquent, vous devez marquer avec volatile. Son vrai que vous n'avez pas besoin de verrouiller des objets si ses 32 bits de taille comme son juste un changement de taille du registre et ainsi atomique.
Il y a un article sur celui-ci ici: www.yoda.arachsys.com/csharp/threads/volatialitive.shtml P>
Il y a aussi quelque chose Appelé domaines de synchronisation forts>. p> Le domaine de synchronisation fournit une synchronisation automatique de l'accès du fil aux objets de manière prétendue. Cette classe a été introduite dans le cadre de l'infrastructure prenant en charge .NET Remoting. Les développeurs souhaitant indiquer qu'une classe est d'avoir accès à ses objets synchronisés doit avoir la classe hériter de contextboundObject et marquez-la avec la synchronisationAttribute de même: p> plus d'informations sur la syncronisation Les domaines peuvent être trouvés ici: MSDN.MicRosoft.com/en-us/magazine/ dd569749.aspx p> p>
Je serais inquiet que le domaine de synchronisation signifie essentiellement que tout accès à l'objet est sérialisé et je n'ai pas besoin de cela dans ce cas. Cela ferait-il de mal au rendement ou est-ce "intelligent" d'une manière ou d'une autre?
Cela semble être une solution assez compliquée pour ce qui semble être un simple loquet. Je pense que la chute volatile code> devant la déclaration de variable serait beaucoup plus facile (LIRE: Mieux).
@Imagist: règle de baiser. Je suis toujours étonné de combien de personnes ne le suivent pas.
Vous pouvez utiliser .Exchange dans ce cas, si vous êtes préoccupé par un verrou laid. P>
Il y a un exemple MSDN qui décrit exactement ce que vous attachez à faire:
Vous pourriez que les personnes déjà écrites marquent la variable avec Cependant, fort>, ce que vous essayez d'accomplir (permettant de communiquer les uns avec les autres par signalisation) est déjà intégré à la framework .NET. P>
Jetez un coup d'œil à volatile code> ou
verrouillage code> it. p>
ManualResetevent code > chez MSDN
. P>
D'oh oui - je sais à ce sujet. Mauvais exemple de ma part. En fait, j'ai vraiment une situation lorsque le "autre fil" examine une valeur d'une variable et l'utilise dans ses opérations. À un moment non déterministe, un fil différent peut modifier cette valeur, puis le thread de boucle commence à utiliser cette nouvelle valeur.
Très bonne question. Je me demande la même chose moi-même :) Je suppose que cela se résume à: "Les threads .Net sont identiques à des threads Windows? Quand peuvent-ils planifier une pause? Sur une instruction native ou sur une instruction CLR?".
@Meeh: dans la carte de threads gérés en courant .NET Runtime Maps directement sur les threads Windows, mais c'est un détail de mise en œuvre.