Quelle est la différence entre Thread.join et Synchronized?

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.

entrez la description de l'image ici

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.