Thread-safe variable globale dans Java
J'essaie de comprendre le fil mécanisme de sécurité en java et j'ai besoin d'aide. J'ai une classe:
public class ThreadSafe {
private Executor executor = new ScheduledThreadPoolExecutor(5);
private long value = 0;
public void method() {
synchronized (this) {
System.out.println(Thread.currentThread());
this.value++;
}
}
private synchronized long getValue() {
return this.value;
}
public static void main(String... args) {
ThreadSafe threadSafe = new ThreadSafe();
for (int i = 0; i < 10; i++) {
threadSafe.executor.execute(new MyThread());
}
}
private static class MyThread extends Thread {
private ThreadSafe threadSafe = new ThreadSafe();
private AtomicBoolean shutdownInitialized = new AtomicBoolean(false);
@Override
public void run() {
while (!shutdownInitialized.get()) {
threadSafe.method();
System.out.println(threadSafe.getValue());
}
}
}
}
Ici, je suis en train de faire la value
thread-safe, pour être accessible que par un seul thread à la fois. Quand je suis en cours d'exécution de ce programme, je vois qu'il y a plus d'un thread d'exploitation sur le value
même si je l'envelopper dans le synchronized
bloc. Bien sûr, cette boucle est infinie mais ses juste un exemple, je suis en arrêt de ce programme manuellement après quelques secondes, j'ai donc:
2470
Thread[pool-1-thread-3,5,main]
2470
Thread[pool-1-thread-5,5,main]
2470
Thread[pool-1-thread-2,5,main]
Différents threads sont l'accès et la modification de cette value
. Quelqu'un peut-il m'expliquer pourquoi est-ce donc? Et comment faire de cette variable globale "thread-safe"?
Assurez-vous de l'avis de ma réponse. Votre
MyThread
classe pas étendre Thread
et doit mettre en œuvre Runnable
.
OriginalL'auteur user2219247 | 2013-05-03
Vous devez vous connecter pour publier un commentaire.
Chaque thread a son propre
ThreadSafe
, et chaqueThreadSafe
a son proprevalue
. En outre,synchronized
méthodes de verrouillage surthis
, de sorte que chaqueThreadSafe
est de verrouillage sur elle-même, et aucun d'entre eux sont partagées entre les threads. Ceci est appelé thread-localité, et c'est la meilleure façon de garantir la sécurité des threads. 🙂Pour obtenir à l'expérience que je pense que vous voulez, vous aurez besoin de changer de
MyThread
tels que son constructeur prend unThreadSafe
argument (au lieu de la construction de l'un). Ensuite, la principale méthode de créer unThreadSafe
et donner à chaqueMyThread
au moment de la construction.OriginalL'auteur yshavit
Vous obtenez la même valeur à chaque fois parce que chacun de vos
Runnable
s a sa propre instance de laThreadSafe
classe.Si vous souhaitez qu'ils partagent la même classe, alors vous allez avoir besoin d'avoir une seule instance de
ThreadSafe
et la passer dans tous vos travaux -- voir ci-dessous. Comme mentionné, unAtomicLong
est la voie à suivre si vous voulez un thread-safe partagélong
.Aussi, votre
MyThread
classe devrait pasextend Thread
. Il devrait plutôtimplements Runnable
. Votre code est de travailler parce queThread
déjàimplements Runnable
. Si vous n'avezmyThread.interrupt()
il ne serait d'interrompre le fil parce que c'est le thread du pool de threads en appelant votrerun()
méthode.Quelque chose comme la suivante devrait fonctionner:
OriginalL'auteur Gray