Je suis confus quand utiliser Thread.join()
et quand utiliser la synchronization
dans une application multi-threading.
Selon moi, les deux bloquent ou attendent que l’exécution soit effectuée par un autre thread.
Cet exemple doit générer 10 A, 10 B et 10 C en séquence l’un après l’autre, comme suit:
1 : A 2 : A 3 : A 4 : A 5 : A 6 : A 7 : A 8 : A 9 : A 10 : A 1 : B 2 : B 3 : B 4 : B 5 : B 6 : B 7 : B 8 : B 9 : B 10 : B 1 : C 2 : C 3 : C 4 : C 5 : C 6 : C 7 : C 8 : C 9 : C 10 : C ----ProGraM ENDS----
Exemple commence ici
class SyncTest extends Thread { SsortingngBuffer sb; public SyncTest(SsortingngBuffer sb) { this.sb = sb; } public void run() { synchronized(sb) { for(int i=1;i<=10;i++){ System.out.println(i+" : "+sb.charAt(0)); } sb.setCharAt(0, (char) (sb.charAt(0)+1)); } } public static void main(String [] args) throws InterruptedException { StringBuffer sb = new StringBuffer("A"); Thread t1=new SyncTest(sb); Thread t2=new SyncTest(sb); Thread t3=new SyncTest(sb); t1.start(); t2.start(); t3.start(); Thread.sleep(1000); System.out.println("----ProGraM ENDS----"); } }
Ici, la sortie s’avère être 10 A, suivie de 10 B, suivie de 10 C dans un ordre séquentiel. Mais je peux aussi utiliser Thread.join
au lieu du bloc synchronized
pour obtenir le même résultat, comme ceci:
public void run() { //removed synchronized statement... for(int i=1;i<=10;i++){ System.out.println(i+" : "+sb.charAt(0)); } sb.setCharAt(0, (char) (sb.charAt(0)+1)); } public static void main(String [] args) throws InterruptedException { StringBuffer sb = new StringBuffer("A"); Thread t1=new SyncTest(sb); Thread t2=new SyncTest(sb); Thread t3=new SyncTest(sb); t1.start(); t1.join(); t2.start(); // wait for t1 to complete t2.join(); t3.start(); // wait for t2 to complete t3.join(); // wait for t3 to complete System.out.println("----ProGraM ENDS----"); }
Quelqu’un peut-il effacer ma confusion sur l’utilisation de ces 2 techniques, c’est-à-dire quand utiliser Thread.join
et quand utiliser la synchronization
en mode multitâche sur Java.
Thread.join()
attend que le thread se termine complètement, alors qu’un bloc synchronized
peut être utilisé pour empêcher deux threads d’exécuter le même morceau de code en même temps.
Il est difficile de conseiller quand utiliser l’un sur l’autre en général, car ils servent des objectives différents. Il est rare de trouver un exemple, tel que votre code, dans lequel la différence entre les deux est minime.
Cela étant dit, dans votre premier exemple, rien ne garantit que le résultat sera alphabétique. Vous ne pouvez pas savoir quel thread va atteindre le bloc synchronized
premier. Donc, dans ce cas particulier, join()
est le plus approprié.
thread.join()
arrête l’exécution du thread actuel jusqu’à la fin du thread joint .. Vous avez commenté correctement .. 🙂
La synchronisation empêche plusieurs threads d’exécuter la partie de code synchronisée sur la même instance.
Le mot clé synchronized
active un mécanisme de locking permettant aux threads de ne pas se chevaucher. La documentation Java décrit ceci comme un moyen “d’empêcher les interférences de thread et les erreurs de cohérence de la mémoire”.
Si vous utilisez join()
, il s’assure que, dès qu’un thread appelle, le thread actuel (thread en cours d’exécution) ne s’exécutera pas tant que le thread que vous avez appelé join n’aura pas terminé. Je pense que le diagramme ci-dessous pourrait aider à mieux visualiser cela.
La source
Sans join()
thread s’exécute en parallèle et dépend de la tranche de temps du système d’exploitation (qui doit commencer en premier) Avec join()
fil s’exécute en série. Par exemple: supposons que vous ayez deux threads avec les deux méthodes appelant join()
MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); t1.join(); // this will be start first. t2.join(); // this will be start only after above.
Maintenant, sans la méthode join()
, aucun des t1
et t2
ne peut commencer en premier. Il n’y a aucune garantie.
instruction synchronized
/ mot clé est utilisé pour surveiller le thread, de sorte qu’un seul thread puisse accéder à cette méthode / variable synchronisée à la fois. Peu importe que vous utilisiez join()
ou non.
Si vous utilisez synchronized
avec join()
, vous avez la garantie que le thread t1
peut uniquement accéder en premier. Sans synchronized
les threads t1
et t2
peuvent accéder à tout moment, mais ces threads démarrent et meurent. en série à cause de join()
.
Ils ne sont évidemment pas identiques, mais s’ils sont utilisés dans le même but (sérialisation access / exécution), les blocs synchronisés peuvent alors être considérés comme une version plus souple que l’utilisation de jointures, car son utilisation est agnostique à propos d’instances de thread particulières sur vous voulez sérialiser l’exécution.
De plus, dans les blocs synchronisés, le concept de bloc de données partagé est plus important que les jointures.
Exemple simple:
Vous avez une table de chaînes statique dans laquelle certains threads mettront des valeurs. La table est initialisée avec “vide”. la table est accessible avec un index statique. Si un thread met une valeur, il augmentera l’index statique.
Si vous synchronisez les threads, vous vous assurez que toute valeur donnée par un thread ne peut pas être remplacée par un autre thread.
si vous utilisez join sur des threads, seul le premier thread joint aura la possibilité de mettre les valeurs dans la table. Comme l’autre attendra, sachant que l’index est incrémenté, il ne pourra pas accéder à la table (exception de pointeur nul) . So Join a rendu l’autre fil inutile.
Cet exemple utilise des threads sur la même instance contenant la méthode synchronisée.