Différence entre bloc synchronisé avec wait / notify et sans eux?

Si je viens d’utiliser la méthode synchronisée, pas attendre / notifier, conservera-t-il toujours la sécurité thread-safe

Quelle est la différence ?

Merci d’avance.

Utiliser synchronized rend une méthode / un bloc accessible uniquement par thread à la fois. Donc, oui, c’est thread-safe.

Les deux concepts sont combinés et non mutuellement exclusifs. Lorsque vous utilisez wait() vous devez posséder le moniteur sur cet object. Donc, vous devez avoir synchronized(..) dessus avant cela. L’utilisation de .wait() arrête le thread actuel jusqu’à ce qu’un autre thread appelle .notify() sur l’object qu’il attend. Ceci est un ajout à synchronized , qui garantit que seulement un thread entrera dans un bloc / une méthode.

alors, après avoir été gêné dans une question d’entrevue à ce sujet, j’ai décidé de le rechercher et de le comprendre à nouveau pour la milliardième fois, mdr.

bloc synchronisé rend le thread de code sécurisé. Aucun doute à ce sujet. Lorsque wait () et notify () ou notifyAll () entrent, vous essayez d’écrire du code plus efficace. Par exemple, si vous avez une liste d’éléments partagés par plusieurs threads, si vous la placez dans le bloc synchronisé d’un moniteur, les threads se relâcheront constamment et exécuteront le code dans les deux sens, lors des changements de contexte ….. .even avec une liste vide!

Wait () est donc utilisé sur le moniteur (l’object à l’intérieur de synchronized (..)) comme mécanisme pour indiquer à tous les threads de se détendre et de cesser d’utiliser cpu cycles jusqu’à nouvel ordre ou notifyAll ().

donc quelque chose comme:

 synchronized(monitor) { if( list.isEmpty() ) monitor.wait(); } ...somewhere else... synchronized(monitor){ list.add(stuff); monitor.notifyAll(); } 

Rendre la méthode synchronisée a deux effets:

Premièrement, il n’est pas possible que deux invocations de méthodes synchronisées sur le même object s’entrelacent. Lorsqu’un thread exécute une méthode synchronisée pour un object, tous les autres threads qui invoquent des méthodes synchronisées pour le même bloc d’object (suspendre l’exécution) jusqu’à ce que le premier thread soit terminé avec l’object

Deuxièmement, lorsqu’une méthode synchronisée se termine, elle établit automatiquement une relation passe-avant avec tout appel ultérieur d’une méthode synchronisée pour le même object. Cela garantit que les modifications apscopes à l’état de l’object sont visibles par tous les threads.

la synchronisation vous aide à garder le code critique.

Si vous souhaitez établir une communication entre plusieurs threads, vous devez utiliser wait () et notify () / notifyAll ().

wait() : force le thread en cours à attendre jusqu’à ce qu’un autre thread appelle la méthode notify () ou la méthode notifyAll () pour cet object.

notify() : réveille un seul thread en attente sur le moniteur de cet object. Si des fils attendent sur cet object, l’un d’eux est choisi pour être réveillé.

notifyAll() : réveille tous les threads en attente sur le moniteur de cet object. Un thread attend sur le moniteur d’un object en appelant l’une des méthodes d’attente.

Cas d’utilisation simple pour l’utilisation de wait () et notify (): problème de producteur et de consommateur .

Le fil consommateur doit attendre que le fil producteur produise des données. wait () et notify () sont utiles dans le scénario ci-dessus. Sur une période de temps, de meilleures alternatives ont été introduites. Reportez-vous à cette page de tutoriel sur la concurrence de haut niveau

En termes simples:

Utilisez synchronized pour protéger la section critique de vos données et protéger votre code.

Utilisez wait() et notify() avec la synchronisation si vous souhaitez établir une communication entre plusieurs threads de manière sécurisée et interdépendants.

Questions SE connexes:

Que signifie “synchronisé”?

Un scénario simple utilisant wait () et notify () en java

Article Java effectif 69: ” Compte tenu de la difficulté d’utiliser l’attente et la notification correctement, vous devez utiliser les utilitaires de simultanéité de niveau supérieur .”

Évitez d’utiliser wait () et notify (): utilisez synchronized , ou d’autres utilitaires de java.util.concurrent , lorsque cela est possible.

Le bloc synchronisé est utilisé si 2 threads du “même object” essaient d’accéder au verrou. Comme la classe d’objects détient le verrou, elle sait à qui donner. Alors que, si 2 threads (disons t2 et t4) de 2 objects (t1 & t2 de obj1 et t3 & t4 de obj 2) essayent d’acquérir le verrou, obj1 ignorera le locking de obj2 et obj2 ignorera le locking de obj1. Par conséquent, les méthodes wait et notify sont utilisées.

par exemple:

 //example of java synchronized method class Table{ synchronized void printTable(int n){//synchronized method for(int i=1;i<=5;i++){ System.out.println(n*i); try{ Thread.sleep(400); }catch(Exception e){System.out.println(e);} } } } class MyThread1 extends Thread{ Table t; MyThread1(Table t){ this.t=t; } public void run(){ t.printTable(5); } } class MyThread2 extends Thread{ Table t; MyThread2(Table t){ this.t=t; } public void run(){ t.printTable(100); } } public class TestSynchronization2{ public static void main(String args[]){ Table obj = new Table();//only one object MyThread1 t1=new MyThread1(obj); MyThread2 t2=new MyThread2(obj); t1.start(); t2.start(); } } 

Deux threads t1 et t2 appartenant au même object, la synchronisation fonctionne donc très bien ici. Tandis que,

 class Table{ synchronized void printTable(int n){//synchronized method for(int i=1;i<=5;i++){ System.out.println(n*i); try{ Thread.sleep(400); }catch(Exception e){System.out.println(e);} } } } class MyThread1 extends Thread{ Table t; MyThread1(Table t){ this.t=t; } public void run(){ t.printTable(5); } } class MyThread2 extends Thread{ Table t; MyThread2(Table t){ this.t=t; } public void run(){ t.printTable(100); } } public class TestSynchronization2{ public static void main(String args[]){ Table obj = new Table(); Table obj1 = new Table(); MyThread1 t1=new MyThread1(obj); MyThread2 t2=new MyThread2(obj1); t1.start(); t2.start(); } } 

Lorsque vous exécutez le programme ci-dessus, la synchronisation ne fonctionne pas car chaque thread appartient à un object différent. Par conséquent, vous devez utiliser wait and notify here.

wait / notify est requirejs lorsque vous souhaitez attendre une condition (par exemple, entrée utilisateur) DANS UN bloc synchronisé.

Utilisation typique:

 synchronized(obj) { // do something while(some condition is not met) { obj.wait(); } // do something other } 

Supposons que vous n’utilisez pas wait (). Ensuite, vous devez implémenter une boucle occupé en interrogeant la condition souhaitée, ce qui nuit aux performances.

 synchronized(obj) { // do something while(some condition is not met) { // busy loop } // do something other } 

Remarque importante: Même si un thread est réveillé par notify () ou notifyAll () depuis un autre thread, le thread de réveil NE garantit PAS de reprendre immédiatement son exécution. Si d’autres threads attendent d’exécuter un bloc synchronisé sur le même object, le thread de réveil doit entrer en compétition avec les threads.