2009-01-25 8 views
0

Je viens de me poser la question suivante: l'accès d'un objet est-il possible en toute sécurité à travers les threads en C#?Atomicité des références d'objet

E.g. avec le code

//Somewhere long ago 
MyClass myVar = new MyClass("First Instance"); 

//Then later, happening at the same time 
//In thread one 
myVar = new MyClass("Second Instance"); 

//In thread two 
myVar.PrintName(); 

Je ne se soucient pas de savoir si la première ou la deuxième instance est utilisée, mais est-il possible que myVar est à un moment pas valable du tout (par exemple, pointant vers un emplacement non existant, peut-être parce que la référence d'objet est que partiellement mis à jour avant utilisé dans l'autre thread)


question latérale sur les verrous:

Si je laisse un verrou - sont alors toutes les écritures en cours confiée à la mémoire?

Ma question ici est si je référence une variable dans un verrou, je sais qu'un seul thread peut accéder au verrou en même temps - mais peut-il arriver que j'écris à la variable dans un thread (et l'écriture est seulement fait au cache), et après que dans l'autre thread même à l'intérieur du verrou obtenir l'ancienne valeur de la variable (parce que le cache n'est pas engagé ou j'ai toujours une ancienne valeur dans le cache de ce thread)?

Répondre

1

À votre première. C'est presque sûrement sûr mais je n'en verrouillerais pas moins. Pour ce qui est de votre cache, de quelle cache parlez-vous, les seules que je peux penser sont les caches de CPU, si nous avions peur de savoir si nous sommes sales et que nous aurions besoin de rinçage, nous serions tous dans beaucoup d'ennuis.

Editer: De votre commentaire, je vois que le cache CPU est ce que vous référez à.

Le matériel multi-processeur et multi-processeur garantit que les données dans un cache obsolète ne seront pas utilisées.

+0

Oui, je voulais dire les caches CPU - donc le code à l'intérieur des zones de verrouillage sont assurés d'être "cache nettoyer"? – Fionn

+0

Tout le code est "cache clean" c'est juste pas quelque chose dont nous devons nous inquiéter, c'est un problème matériel;). Il n'y a pas de situations dans lesquelles le codage thread-safe peut nécessiter un travail supplémentaire pour rendre le cache propre. Le code OTH thread-unsafe est dangereux même avec un seul processeur/cache. – AnthonyWJones

0

L'exemple de code de votre question est thread-safe. Évidemment, en fonction de ce que vous faites à l'intérieur de ce constructeur, mais "en général" l'arbitre myVar sera valide (en général, il y a des choses de bas niveau que vous pourriez faire, comme les FormatterServices, etc.). Un nouvel objet sera créé en utilisant le constructeur, et sera retourné automatiquement au bon thread. Pour moi, c'est l'un des meilleurs moyens de s'assurer que le code est sûr pour les threads, en créant de nouveaux objets sur chaque thread.

0

Je dirais que tant que vous n'êtes pas explicitement déréférencé les objets, il n'y a pas de menace d'une référence nulle. La seule heure peut être si vous démarrez le thread deux avant d'initialiser myVar. Je ne pense pas que vous ayez besoin d'un verrou dans cet exemple simple. En ce qui concerne votre question secondaire, à quelle cache faites-vous référence?

1

Je sais que votre question concerne .NET et je ne peux pas vous donner la réponse. Cependant, en Java, ce code ne serait définitivement PAS sûr. Le risque est que le réordonnancement de code (une étape d'optimisation) verrait la mise à jour de la référence d'objet AVANT que le constructeur ait terminé son exécution - le second thread pourrait donc voir une version partiellement construite du second objet. En java, vous pouvez résoudre ce problème en rendant l'objet de référence volatile, ou le protéger derrière une sorte de AtomicReference (ou par la synchronisation, bien sûr) - qui imposent une «barrière de mémoire» qui limite l'optimisation qui peut être fait afin de s'assurer qu'un objet partiellement construit n'est jamais visible.Comme je l'ai dit, je ne connais pas assez le modèle de mémoire .NET pour savoir si .NET aura le même problème.

Questions connexes