10
votes

Attendre () / notifier () synchronisation

J'essaie de vérifier comment attendre / notifier les œuvres en Java.

code: xxx

Sortie renvoyée < / strong> xxx

Je m'attendais lors de la notification () est exécuté l'attente sera Out & System.out.println ("attendre"); sera imprimé. Mais il semble que cela ne soit imprimé que lorsque t a terminé son exécuté () .


4 commentaires

Vous ne synchronisez pas sur les mêmes objets


MyRunnable.Ce == r! = T


@ Raul8 Modification Question et coller dans la réponse rend la réponse correcte non valide. Il serait préférable d'ajouter une autre question.


Je comprends que vous étudiez comment attendez / notify travail. Mais de toute façon, je vous recommanderais vivement de vous recommander de préférer utiliser Java's API simultanée de haut niveau dans votre code. Il est très facile de faire des erreurs difficiles à trouver dans le code de simultané de bas niveau (comme vous l'avez vu dans cet exemple).


3 Réponses :


11
votes

Les serrures de moniteur d'objet doivent être effectuées une seule référence du même verrouillage ...

dans votre exemple, vous êtes en attente code> sur une instance du fichier code>, Mais en utilisant notifier code> à partir du exécutable code>. Au lieu de cela, vous devez utiliser un seul objet de verrouillage commun ... Par exemple P>

    public static class MyRunnable implements Runnable {

        public void run() {
            System.out.println("entering run method");
            synchronized (LOCK) {
                System.out.println("entering syncronised block");
                LOCK.notify();
                System.out.println("leaving syncronized block");
            }
            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("leaving run method");
        }
    }


2 commentaires

Merci ... mais j'ai essayé votre code .. mais cela ne fonctionne toujours pas. Code en question mise à jour


FYI thread.sleep (les deux formulaires) est une méthode statique qui met toujours le fil d'appel pour veille; Ainsi, thread.CurrentTthread (). Sleep (1000) est sémantiquement redondant et probablement trompeur (par exemple, appeler t.sleep (1000) mettrait le fil d'appel au sommeil, pas t ).



5
votes

Réponse au code mis à jour:

de thread.sleep. () Javadoc:

provoque le sommeil actuellement en cours d'exécution (cesser temporairement l'exécution) pour le Nombre spécifié de millisecondes, sous réserve de la précision et de la précision des minuteries du système et planificateurs. Le fil ne perd pas la propriété des moniteurs .

Si vous appelez WHING.SLEEP tandis que dans un bloc synchronisé, d'autres threads ne pourront pas entrer dans le bloc synchronisé. Vous ne devriez jamais prendre de temps à prendre du temps dans un bloc synchronisé pour éviter cela.


0 commentaires

2
votes

Remarque (comme d'autres l'indiquent également) que vous devez utiliser le même objet pour le verrouillage / la synchronisation dans les deux threads.

Si vous souhaitez que votre fil principal continue immédiatement après notifier est Appelé, vous devez abandonner temporairement la serrure. Sinon attendre sera appelé uniquement après que le fil secondaire quitte le bloc synchronisé . Et ce n'est jamais une bonne idée de garder une serrure dans un calcul de course longue!

Une façon de réaliser est d'utiliser attendre (int) sur le verrouillage au lieu de Dormez , car attendre libère le verrou de synchronisation temporairement: xxx

Cependant, l'utilisation de ces primitives de bas niveau peut être très sujette à l'erreur et Je découragerais de les utiliser. Au lieu de cela, je vous suggère d'utiliser les primitives de haut niveau de Java pour cela. Par exemple, vous pouvez utiliser Countownlatch qui permet d'attendre un thread jusqu'à ce que d'autres threads comptent sur zéro: xxx

ici, vous n'avez pas à synchroniser tout ce que le loquet fait tout pour vous. Il y a beaucoup d'autres primitives que vous pouvez utiliser - SEMAPHORES, un échangeur, des files d'attente de thread-coffre, etc. Explorer le Java.Util.ConCurrent package.

peut-être encore meilleure solution consiste à Utilisez une API de niveau encore plus haute, telle que AKKA fournit. Là vous travaillez avec acteurs ou logicielle mémoire transactionnelle , qui peut être composée facilement et vous épargner de la plupart des problèmes de concurrence.


0 commentaires