Un int volatile en Java thread-safe?

Est un volatile int en Java thread-safe? Autrement dit, Peut-on le lire et l'écrire en toute sécurité sans le verrouiller?

48
demandé sur hopper 2011-10-18 13:35:15

6 réponses

Oui, vous pouvez le lire et l'écrire en toute sécurité - mais vous ne pouvez rien faire composé tel que l'incrémenter en toute sécurité, car c'est un cycle de lecture/modifier/écrire. Il y a aussi la question de son interaction avec l'accès aux variables autres .

la nature précise de volatile est franchement déroutante (voir la section modèle de mémoire de la JLS pour plus de détails ) - je voudrais personnellement généralement utiliser AtomicInteger à la place, comme un moyen plus simple de m'assurer que je l'obtiens bien.

60
répondu Jon Skeet 2016-02-22 20:36:21

[...] comme de pouvoir être lu et écrit en toute sécurité sans verrouillage?

Oui, une lecture résultera toujours en la valeur de la dernière écriture, (et les deux lisent et écrivent sont des opérations atomiques).

Un volatile de lecture / écriture introduit une sorte de passe-avant dans l'exécution.

de la spécification de langage Java Chapitre 17: fils et Serrures

une écriture à un champ volatile (§8.3.1.4) se produit-avant chaque lecture subséquente de ce champ.

en d'autres termes, lorsque vous traitez avec des variables volatiles, vous ne devez pas explicitement synchroniser (introduire une relation happens-before) en utilisant le mot-clé synchronized afin de s'assurer que le thread obtient la dernière valeur écrite à la variable.

comme Jon Skeet le souligne, l'utilisation de variables volatiles est limitée, et vous devriez en général envisager d'utiliser les classes du paquet java.util.concurrent à la place.

6
répondu aioobe 2011-10-18 09:39:15

accès à volatile int en Java sera thread-safe. Quand je dis "accès", Je veux dire le fonctionnement unitaire, comme volatile_var = 10 ou int temp = volatile_var (en gros, écrire/lire avec des valeurs constantes). Le mot-clé Volatile en java assure deux choses:

  1. en lisant vous obtenez toujours la valeur en mémoire principale. Généralement à des fins d'optimisation JVM utilisent des registres ou en termes plus généraux mémoire locale stockage/accès de l'ennemi variable. Ainsi, dans un environnement multi-threadé, chaque thread peut voir une copie différente de la variable. Mais le rendre volatile fait en sorte que l'écriture à variable est rincé à la mémoire principale et la lecture à elle se produit aussi de la mémoire principale et donc s'assurer que le fil voir à la copie droite de variable.
  2. L'accès au volatile est automatiquement synchronisé. Ainsi, JVM assure une commande en lecture/écriture sur la variable.

cependant Jon Skeet mentionne à juste titre que dans les opérations non atomiques (volatile_var = volatile + 1) différents fils peuvent obtenir un résultat inattendu.

2
répondu Saurabh 2015-05-15 20:21:40

si une variable volatile n'est dépendante d'aucune autre variable volatile, son thread safe pour le fonctionnement en lecture. En cas d'écriture volatile ne garantit pas la sécurité du fil.

supposons que vous avez une variable i qui est volatile et que sa valeur dépend d'une autre variable volatile, disons J. Maintenant la variable D'accès Fil-1 J et incrémente et est sur le point de la mettre à jour dans la mémoire principale à partir du cache CPU. Dans le cas où le fil-2 lit le

variable i avant Fil-1 peut effectivement mettre à jour le j dans la mémoire principale. La valeur de i sera que par l'ancienne valeur de j qui serait incorrect. Il est aussi appelé lecture Sale.

0
répondu Ajay Verma 2017-10-11 07:50:29

pas toujours.

ce n'est pas sûr si plusieurs threads sont en train d'écrire et de lire la variable. C'est sûr si vous avez un fil d'auteur et plusieurs fils de lecteur.

si vous cherchez du fil en toute sécurité, utilisez AtomicXXX classes

une petite boîte à outils de classes qui prennent en charge la programmation de thread-safe sans verrouillage sur des variables simples.

In essence, les classes dans ce paquet étendent la notion de valeurs volatiles, les champs, et les éléments de tableau à ceux qui fournissent également une opération de mise à jour conditionnelle atomique de la forme:

boolean compareAndSet(expectedValue, updateValue);

reportez-vous à @teto réponse ci-dessous post:

Volatile boolean vs AtomicBoolean

0
répondu Ravindra babu 2017-10-11 14:02:26

1) si deux threads sont à la fois la lecture et l'écriture à une variable partagée, alors l'utilisation du mot-clé volatile pour cela n'est pas suffisant. Vous devez utiliser un synchronisé dans ce cas, afin de garantir que la lecture et l'écriture de la variable est atomique. Lire ou écrire une variable volatile ne bloque pas les threads lire ou écrire. Pour ce faire, vous devez utiliser le mot-clé synchronisé autour des sections critiques.

2) comme alternative à un bloc synchronisé vous pourrait également utiliser l'un des nombreux types de données atomiques trouvés dans le java.util.simultanées paquet. Par exemple, la référence AtomicLong ou Atomic ou l'une des autres.

c'est sûr si vous avez un fil d'auteur et plusieurs fils de lecteur.

class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null)
helper = new Helper();
}
}
return helper;
}
}

Note: Si helper est immuable alors pas besoin de mot-clé volatile.Ici singleton fonctionnera correctement.

dans le cas d'un compteur incrémenté de fils multiples (lecture écriture opération) ne donnera pas la bonne réponse. Cette condition est également illustrée par la condition de race.

public class Counter{
private volatile int i;
public int increment(){
i++;
}
}

NOTE: ici volatile n'aidera pas.

0
répondu Rahul Saxena 2018-01-31 04:02:26