Si plusieurs threads peuvent accéder à un champ, doit-il être marqué comme volatile?

StackOverflow https://stackoverflow.com/questions/1621495

  •  06-07-2019
  •  | 
  •  

Question

Lecture de quelques discussions ( problèmes courants de concurrence , mot clé volatile , modèle de mémoire ) Je suis confus au sujet des problèmes de simultanéité dans Java.

J'ai beaucoup de champs auxquels plusieurs threads ont accès. Dois-je les passer en revue et les marquer comme volatiles?

Lorsque je construis une classe, je ne sais pas si plusieurs threads y auront accès. Il est donc sûrement dangereux de laisser un champ pas être volatil. Par conséquent, si j'ai bien compris, il y a très peu de cas ne l'utilisez pas. Est-ce correct?

Pour moi, cela est spécifique aux machines virtuelles Java version 1.5 et ultérieure, mais ne vous sentez pas limité à répondre à ma configuration spécifique.

Était-ce utile?

La solution

Si un champ est accédé par plusieurs threads, il doit être volatile ou final , ou utilisé uniquement avec des blocs synchronisés. Sinon, les valeurs attribuées risquent de ne pas être visibles par d'autres threads.

Une classe doit être spécialement conçue pour un accès simultané par plusieurs threads. Le simple marquage de champs volatiles ou finaux ne suffit pas pour la sécurité du filetage. Il y a des problèmes de cohérence (atomicité des modifications apportées à plusieurs champs), des préoccupations concernant la signalisation inter-thread (par exemple, en utilisant wait et notify ), etc.

Il est donc plus sûr de supposer qu'un objet ne doit être visible que par un seul thread, sauf indication contraire. Rendre tous vos objets thread-safe n'est pas nécessaire, et est coûteux en termes de vitesse des logiciels, mais plus important encore, en termes de coût de développement.

Au lieu de cela, les logiciels doivent être conçus de manière à ce que les threads simultanés interagissent le moins possible, de préférence pas du tout. Les points où ils interagissent doivent être clairement identifiés afin que les contrôles de concurrence appropriés puissent être conçus.

Autres conseils

Eh bien, vous avez lu ces autres questions et je suppose que vous avez déjà lu les réponses, je vais donc souligner quelques points clés:

  1. vont-ils changer? sinon, vous n'avez pas besoin de volatile
  2. Si oui, la valeur d'un champ est-elle liée à un autre? Si oui, allez au point 4
  3. combien de threads vont le changer? si seulement 1, alors tout ce dont vous avez besoin est volatil
  4. si la réponse au numéro 2 est " no " ou si plusieurs threads vont y écrire, alors seul le composant volatile ne suffit pas , vous devrez probablement synchroniser l'accès

Ajouté:
Si le champ fait référence à un objet, il aura ses propres champs et toutes ces considérations s’appliqueront également à ces champs.

Si vous devez demander, utilisez des verrous. volatile peut être utile dans certains cas, mais il est très, très difficile d’obtenir des résultats corrects. Par exemple:

class Foo {
  private volatile int counter = 0;
  int Increment() {
    counter++;
    return counter;
  }
}

Si deux threads exécutent Increment () en même temps, il est possible que le résultat soit counter = 1 . En effet, l'ordinateur récupère d'abord le compteur , en ajoute un, puis le sauvegarde. Volatile oblige simplement la sauvegarde et le chargement dans un ordre spécifique par rapport aux autres instructions.

Notez que synchronized élimine généralement la nécessité de volatile - si tous les accès à un champ donné sont protégés par le même moniteur, volatile jamais besoin.

Utiliser volatile pour créer des algorithmes sans verrouillage est très, très difficile. respectez synchronized à moins que vous ne disposiez d'une preuve irréfutable que c'est déjà trop lent et que vous avez effectué une analyse détaillée de l'algorithme que vous envisagez de mettre en œuvre.

La réponse courte est non. Les problèmes de filetage nécessitent plus de réflexion et de planification que cela. Voir this pour connaître certaines limitations concernant les cas où l'aide volatile filetage et quand il ne fait pas. La modification des valeurs doit être correctement synchronisée, mais très généralement, la modification nécessite l’état de plusieurs variables à la fois. Disons par exemple que vous avez une variable et que vous souhaitez la modifier si elle répond à un critère. La lecture du tableau et l'écriture sur le tableau sont des instructions différentes et doivent être synchronisées ensemble. La volatilité ne suffit pas.

Considérons également le cas où la variable fait référence à un objet mutable (disons un tableau ou une collection), alors l'interaction avec cet objet ne sera pas thread-safe simplement parce que la référence est volatile.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top