97 votes

Sont les variables statiques sont partagées entre les threads?

Mon professeur dans un niveau supérieur de classe java sur le filetage a dit quelque chose que je n'étais pas sûr de.

Il a déclaré que le code suivant ne serait pas nécessairement de mise à jour de l' ready variable. Selon lui, les deux fils ne partageons pas nécessairement la variable statique, en particulier dans le cas lorsque chaque thread (thread principal contre ReaderThread) est en cours d'exécution sur son propre processeur et donc ne partage pas les mêmes registres/cache/etc et un CPU de ne pas mettre à jour les autres.

Essentiellement, il dit qu'il est possible qu' ready est mis à jour dans le thread principal, mais PAS dans le ReaderThread, de sorte que ReaderThread en boucle à l'infini. Il a également affirmé qu'il était possible que le programme d'impression de '0' ou '42'. Je comprends comment '42" pourrait être imprimé, mais pas de "0". Il a mentionné ce serait le cas lorsque l' number variable est définie sur la valeur par défaut.

J'ai pensé que peut-être il n'est pas garanti que la statique de la variable est mise à jour entre les threads, mais cela me semble très étrange pour Java. L' ready volatile corriger ce problème?

Il a montré ce code:

public class NoVisibility { 
 private static boolean prêt; 
 private static int nombre; 
 private static de la classe ReaderThread extends Thread { 
 public void run() { 
 while (!prêt) Thread.rendement(); 
 Système.out.println(nombre); 
 } 
 } 
 public static void main(String[] args) { 
 nouveau ReaderThread().start(); 
 nombre = 42; 
 prêt = true; 
 } 
}

78voto

Nathan Hughes Points 30377

Il n'y a pas de visibilité spécifiques à des variables statiques. Il y a une visibilité imposées par la JVM du modèle de mémoire. Voici un article qui parle de la mémoire de modèle et la façon dont les écritures deviennent visibles pour les threads. Vous ne pouvez pas compter sur les changements à un fil fait de devenir visible pour les autres threads en temps opportun (en fait la JVM n'a aucune obligation de faire ces changements visibles pour vous à tous), sauf si vous établir un passe-avant la relation, voici une citation de ce lien (fournis dans le commentaire par Jed Wesley-Smith):

Le chapitre 17 de l'Java Langage de Spécification définit ce rapport sur les opérations de mémoire tels que les lectures et les écritures de variables partagées. Les résultats d'une écriture par un seul thread sont garantis pour être visible à une lecture par un autre thread que si l'opération d'écriture qui se passe avant que l'opération de lecture. La synchronisation et de la volatilité des constructions, ainsi que le Thread.start() et du Fil.join() les méthodes, le formulaire se passe-avant le les relations. En particulier:

  • Chaque action dans un thread se passe-avant chaque action dans ce thread qui vient plus tard dans le programme de commande.

  • Un déverrouillage (synchronisé bloc ou de la méthode de sortie) d'un moniteur se passe-avant chaque verrou (synchronisé bloc ou de la méthode d'entrée) de la même moniteur. Et parce que le passe-avant, la relation est transitive, toutes les actions d'un fil avant le déverrouillage se passera-avant toutes les actions ultérieures à n'importe quel thread de verrouillage que moniteur.

  • Une écriture dans un champ volatile se passe-avant chaque lecture ultérieure de ce même champ. Les écritures et les lectures de la volatilité des champs similaires à assurer la cohérence de mémoire des effets que l'entrée et la sortie de moniteurs, mais n'entraîne pas l'exclusion mutuelle de verrouillage.

  • Un appel à lancer sur un thread se passe-avant toute action sur la mise en route fil.

  • Toutes les actions dans un thread se passera-avant toute autre thread renvoie à partir d'une jointure sur ce thread.

37voto

Bert F Points 27237

Il parlait de la visibilité et de ne pas être pris trop à la lettre.

Les variables statiques sont en effet partagées entre les threads, mais les modifications apportées à un fil peut ne pas être visible à un autre thread immédiatement, ce qui semble comme il y a deux copies de la variable.

Cet article présente une vue qui est cohérent avec la façon dont il a présenté l'info:

Tout d'abord, vous devez comprendre un peu quelque chose à propos de la Java du modèle de mémoire. J'ai un peu de mal au cours des années à expliquer brièvement et bien. À compter d'aujourd'hui, la meilleure façon que je peux penser à décrire, c'est si vous vous imaginer de cette façon:

  • Chaque thread en Java prend place dans un espace mémoire séparé (ce qui est clairement faux, si patient avec moi sur ce point).

  • Vous avez besoin d'utiliser des mécanismes pour garantir que la communication se fait entre ces fils, comme vous le feriez sur un passage de messages système.

  • Mémoire écrit qui se produisent dans un thread peut "passer au travers" et d'être vu par un autre thread, mais ce n'est pas garanti. Sans communication explicite, vous ne pouvez pas garantir qui écrit vu par les autres threads, ou même l'ordre dans lequel ils ont vu.

...

thread model

Mais encore une fois, c'est tout simplement un modèle mental à réfléchir sur le filetage et le volatile, pas littéralement comment la machine fonctionne.

13voto

axtavt Points 126632

Fondamentalement, il est vrai, mais en fait le problème est plus complexe. La visibilité des données partagées peuvent être affectées non seulement par des caches CPU, mais aussi par l'ordre d'exécution des instructions.

Donc Java définit un Modèle de Mémoire, que les états en vertu de laquelle les circonstances threads peuvent voir l'état cohérent de données partagées.

Dans votre cas particulier, l'ajout d' volatile garantit la visibilité.

8voto

biziclop Points 21446

Ils sont "partagés", bien sûr, dans le sens que tous deux se réfèrent à la même variable, mais ils n'en voient pas nécessairement les uns des autres mises à jour. Cela est vrai pour n'importe quelle variable, et pas seulement statique.

Et en théorie, écrit par un autre thread peut sembler être dans un ordre différent, à moins que les variables sont déclarées volatile ou de l'écrit sont explicitement synchronisé.

5voto

Kirk Woll Points 34601

Au sein d'un seul chargeur de classe, les champs statiques sont toujours partagés. Explicitement la portée de données pour les threads, vous souhaitez utiliser une installation, comme ThreadLocal.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X