Variables statiques et multithreading en java

Un membre statique d’une classe est-il présent comme une seule instance par processus ou thread? Ce qui signifie que chaque thread a sa propre copie de la variable membre statique de la classe?

Mon estimation est par processus, ai-je raison?

Les champs statiques ont donné une valeur par chargeur de classe.

Si vous voulez une valeur par thread, créez un ThreadLocal statique.

Comme déjà mentionné, static champs static ont une valeur par chargeur de classe. Cependant, je pensais pouvoir commenter le texte suivant de votre question:

chaque thread a sa propre copie de la variable membre statique de la classe

C’est correct même si le diable est dans les détails. Chaque thread peut avoir sa propre copie du champ dans son propre espace mémoire / cache local à moins que le champ ne soit marqué avec volatile ce qui oblige le champ à être entouré d’une barrière de mémoire qui provoque une synchronisation de la mémoire à chaque access / mise à jour.

Sans mise à jour, toutes les mises à jour et les lectures dans un champ static sont effectuées dans le stockage du thread local et ne sont mises à jour que lorsqu’un thread traverse une barrière de mémoire. Sans les barrières de mémoire, il n’y a aucune garantie concernant l’ordre des opérations de données et le moment où les mises à jour seront partagées avec d’autres threads.

Voici une page décente sur le modèle de mémoire Java et un aperçu de certains des défis .

Une copie de variable static par chargeur de classe a chargé cette classe. Cela signifie plus ou moins par processus, mais vous devez être conscient de la différence.

Par exemple, lorsque deux applications Web ont la même classe groupée, la classe sera chargée deux fois, ce qui donnera deux copies du même champ static .

Si vous avez besoin d’une variable ayant une valeur indépendante sur une base de thread, consultez ThreadLocal .

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html

Variables de classe (champs statiques) Une variable de classe est un champ déclaré avec le modificateur static; Cela indique au compilateur qu’il existe exactement une copie de cette variable, quel que soit le nombre de fois où la classe a été instanciée. Un champ définissant le nombre d’engrenages pour un type de vélo particulier peut être marqué comme statique car, conceptuellement, le même nombre d’engrenages s’appliquera à toutes les instances. Le code static int numGears = 6; créerait un tel champ statique. De plus, le mot-clé final pourrait être ajouté pour indiquer que le nombre de vitesses ne changera jamais.

Les fils n’ont aucun rapport avec cela. (Le chargeur de classe, par contre, le fait. Si vous utilisez plusieurs chargeurs de classe dans votre application, toutefois, vous en êtes probablement à un point où vous comprenez cela).

Le problème des threads est le suivant: la vue “10000 pieds” de la mémoire Java indique qu’il existe une seule partie de la mémoire partagée par toutes les classes, tous les objects, tous les chargeurs de classes et tous les threads de la machine virtuelle Java en cours d’exécution. accessible depuis un endroit du code est accessible partout ailleurs (avec une référence appropriée). La seule exception concerne les registres et la stack d’exécution, qui sont conceptuellement basés sur un thread.

Cela fonctionne très bien avec un seul processeur, où les threads s’exécutent à tour de rôle dans un seul ensemble de registres et d’ALU. Mais la plupart des ordinateurs modernes ont plusieurs processeurs, de sorte que plusieurs threads peuvent s’exécuter en même temps. Si ces processeurs devaient tous référencer la même mémoire physique, alors (sur la base de l’expérience vécue), vous ne pourriez obtenir qu’une amélioration d’environ 1,5 fois les performances avec 4 processeurs, et cela dégénérerait à partir de là.

Ainsi, “cache” est utilisé, de sorte que chaque processeur a sa propre copie privée de bits et de morceaux de la mémoire plus grande. La plupart du temps, les processeurs s’adressent à des zones de mémoire entièrement différentes. Cela fonctionne donc très bien, mais occasionnellement (comme lorsqu’il s’agit d’un object “partagé”), ils doivent “se battre” sur le même ensemble d’octets.

La solution consiste à établir des protocoles afin que deux processeurs ne tentent pas de modifier les mêmes emplacements de stockage en même temps (ou presque) et à ce qu’un processeur modifié soit “vidé” du magasin principal et que les autres processeurs soient informés les modifications et conseillé de recharger leur vue des données modifiées.

Mais il est (incroyablement) inefficace de le faire après chaque opération (et, très franchement, les concepteurs de matériel ont largement esquivé le problème et imposé au logiciel plus de travail qu’il n’est probablement justifié). Ainsi, les schémas sont utilisés de telle sorte que le vidage et le rechargement de données ne se produisent que sur certaines “limites” ou lorsque certains types spéciaux de références sont définis.

Notez que tout cela n’a absolument rien à voir avec le fait qu’une variable soit “statique” ou non, ni le fait que les objects soient “immuables”. C’est inhérent à l’architecture matérielle multiprocesseur moderne, combinée au modèle de thread Java.

Comme SLaks en proposait un par machine virtuelle, veillez à ce que deux threads conservant un verrou sur la même référence statique se bloquent, car il n’y a qu’une seule référence de ce type par machine virtuelle. Mais ils ne bloqueront pas les threads faisant référence à des variables d’instance.

En fait, la variable de classe correspond à la classe, car elle ne partage qu’une seule mémoire. Les modifications apscopes par chaque instance de classe peuvent donc modifier la variable de classe.