Jetons un coup d'œil à ce code:
Import java.util.bitset; Thread t1 = new thread (new Runnable () {public void run () {try {latch.await (); thread.sleep (1000);} catch (exception ex) {} bs.set (1);}); Thread t2 = new thread (new Runnable () {public void run () {try {latch.await (); thread.sleep (1000);} catch (exception e) {} bs.set (2);}}) start (); t2.Start (); Latch.CountDown (); :}}La question est, quel est le résultat de cette sortie de code? Quels résultats peuvent-ils sortir?
Jetons un coup d'œil à ce que fait ce programme:
Ensuite, nous devons construire des cas de test pour vérifier ces comportements. De toute évidence, l'un d'eux ne peut exécuter cet exemple, puis observer les résultats et répondre aux questions ci-dessus.
La prudence peut faire une coïncidence
Heureusement, nous pouvons utiliser des outils. JCStress est un outil de test pour résoudre ces problèmes.
Nous pouvons facilement rédiger notre cas de test en tant que formulaire que JCSTRESS peut reconnaître. En fait, il a préparé une variété d'interfaces pour nous. Nous avons besoin d'un exemple.
Nous utilisons une interface Actor2_arbiter1_teest, BitSet, BooleanResult2>. Nous devons trouver un Java 8 JVM pour l'exécuter, mais maintenant ce n'est pas un problème.
Regardez la mise en œuvre ci-dessous.
Classe publique anExamplest implémente actor2_arbiter1_test <bitset, booleanresult2> {@Override public void actor1 (bitset s, booleanresult2 r) {s.set (1);} @Override public void actor2 (bitset s, booleanresult2 r) {s.set (2 );} @Override public void arbiter1 (bitset s, booleanresult2 r) {r.r1 = s.get (1); ;} @Override public boolenRsult2 newResult () {return new booleanresult2 ();}}
Maintenant, lors de l'exécution de ce test, le contrôle essaiera toutes sortes de trucs pour obtenir toutes les combinaisons possibles de facteurs qui conduisent ces actions: parallèle ou non-Merger, il n'y a pas de détection de charge, et il y a plusieurs fois sur une seule ligne, plusieurs fois, Plusieurs fois, plusieurs fois, souvent, tous les résultats possibles seront enregistrés.
Lorsque vous voulez savoir comment se déroule votre code parallèle, c'est une meilleure façon de creuser une pensée creuse et de penser à tous les détails que vous.
De plus, afin d'utiliser la commodité complète apportée par les contraintes JCStress, nous devons lui fournir une explication des résultats possibles.
<test name = "org.openjdk.jcstress.tests.custom.anExamplest"> <contribué-by> oleg shelajev </ contributed-by> <descriptions si Bitset fonctionne bien avec une synchronisation. > Match> [true, true] </ correspond> <attend> acceptable </ attend> <Description> Voir toutes les mises à jour intactes. / Attendre> <description> T2 Résultat T1. > </ Case> <nmatched> <spériqués> interdits </ften> <Description> Tous les autres cas sont sous Unlenexpection.
Maintenant, nous sommes prêts à ce que cette bête commence à rugir.
java -xx: + unlockdiagnosticvmoptions -xx: + whiteboxapi -xx: -ResterrictContend -jar tests -Custot / Target / jcstress.jar -t = ". * anExamplest"
Le résultat que nous obtenons est un rapport élégant.
Il est clair que nous pouvons non seulement obtenir les résultats attendus, c'est-à-dire que les deux threads ont réglé leurs positions, mais rencontrent également une condition concurrentielle, et un fil couvrira le résultat d'un autre thread.
Même si vous voyez une telle chose, vous devez avoir la mentalité calme des "les gens de la montagne ont leurs propres trucs", n'est-ce pas?
Soit dit en passant, si vous réfléchissez à la façon de modifier ce code, la réponse est de lire soigneusement la classe Bitset dans Javadoc et de réaliser qu'il ne s'agit pas d'une sécurité de thread et nécessite une synchronisation externe. Cela peut facilement être réalisé en augmentant les valeurs de réglage des blocs synchrones.
synchronisé (bs) {bs.set (1);}