web-dev-qa-db-fra.com

Que fait synchronized () / wait () / notifyAll () en Java?

Duplicata possible:
synchronisation Java

Je lis le livre Début Android Jeux.

Il utilise beaucoup synchronized() mais je ne comprends pas vraiment ce qu'il fait. Je n'ai pas utilisé Java depuis longtemps et je ne sais pas si j'ai déjà utilisé le multithreading.

Dans les exemples Canvas, il utilise synchronized(this). Cependant, dans l'exemple OpenGL ES, il crée un objet appelé stateChanged puis utilise synchronized(stateChanged). Lorsque l'état du jeu change, il appelle stateChanged.wait() puis stateChanged.notifyAll();

Du code:

    Object stateChanged = new Object();

    //The onPause() looks like this:
    public void onPause()
        {
            synchronized(stateChanged)
            {
                if(isFinishing())
                    state = GLGameState.Finished;
                else
                    state = GLGameState.Paused;

                while(true)
                {
                    try
                    {
                        stateChanged.wait();
                        break;
                    } catch(InterruptedException e)
                    {
                    }
                }
            }
        }
//The onDrawSurface looks like this:
public void onDrawFrame(GL10 gl)
    {
        GLGameState state = null;
        synchronized(stateChanged)
        {
            state = this.state;
        }

        if(state == GLGameState.Running)
        {

        }

        if(state == GLGameState.Paused)
        {
            synchronized(stateChanged)
            {
                this.state = GLGameState.Idle;
                stateChanged.notifyAll();
            }
        }

        if(state == GLGameState.Finished)
        {
            synchronized(stateChanged)
            {
                this.state = GLGameState.Idle;
                stateChanged.notifyAll();
            }
        }
    }

//the onResume() looks like this:
synchronized(stateChanged)
        {
            state = GLGameState.Running;
            startTime = System.nanoTime();
        }
30
Tiago Costa

Ce Java peut probablement vous aider à comprendre ce que fait l'utilisation synchronisée sur un objet.

Lorsque object.wait() est appelé, il libérera le verrou maintenu sur cet objet (ce qui se produit lorsque vous dites synchronized(object)) et gèle le thread. Le thread attend ensuite que object.notify() ou object.notifyAll() soit appelé par un thread séparé. Une fois que l'un de ces appels se produit, il permet à tous les threads arrêtés en raison de object.wait() de continuer. Cela ne signifie pas que le thread qui a appelé object.notify() ou object.notifyAll() se fige et passe le contrôle à une attente thread, cela signifie simplement que ces threads en attente peuvent maintenant continuer, alors qu'avant ils ne l'étaient pas.

31
tdashroy

Le mot clé synchronized est utilisé pour garder les variables ou les méthodes thread-safe. Si vous encapsulez une variable dans un bloc synchronisé comme ceci:

synchronized(myVar) {
    // Logic involing myVar
}

Ensuite, toute tentative de modification de la valeur de myVar à partir d'un autre thread pendant l'exécution de la logique à l'intérieur du bloc synchronisé attendra la fin de l'exécution du bloc. Il garantit que la valeur entrant dans le bloc sera la même tout au long du cycle de vie de ce bloc.

50
Jason Robinson

Lorsqu'il est utilisé comme ceci:

private synchronized void someMehtod()

Vous obtenez ces effets:

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

2. Deuxièmement, lorsqu'une méthode synchronisée se termine, elle établit automatiquement une relation passe-avant avec toute invocation ultérieure d'une méthode synchronisée pour le même objet. Cela garantit que les modifications de l'état de l'objet sont visibles pour tous les threads.

(Tiré de ici )

Vous obtenez un effet similaire lorsque vous utilisez un bloc de code synchronisé:

private void someMethod() {
  // some actions...

  synchronized(this) {
    // code here has synchronized access
  }

  // more actions...
}

Comme expliqué ici

10
Tanner Perrien

Java (sur lequel Android est basé) peut s'exécuter sous plusieurs threads qui peuvent utiliser plusieurs cœurs de processeur. Le multi-threading signifie que vous pouvez avoir Java faisant deux processus) au même moment. Si vous avez un bloc de code ou une méthode dont vous devez vous assurer qu'il ne peut être exploité que par un thread à la fois, vous synchronisez ce bloc de code.

Voici l'explication officielle Java d'Oracle

Il est important de savoir qu'il y a un coût processeur/io lié à l'utilisation de la synchronisation et que vous ne souhaitez l'utiliser que lorsque vous en avez besoin. Il est également important de rechercher ce qui Java sont thread-safe. Par exemple, l'opérateur d'incrémentation ++ n'est pas garanti pour être thread-safe, alors que vous pouvez facilement créer un bloc de code synchronisé qui incrémente une valeur en utilisant + = 1.

4
TroyJ

un seul thread peut être actif et à l'intérieur du bloc synchronisé par un objet donné. l'appel d'attente s'arrête abandonne ce droit et désactive le thread actuel jusqu'à ce que quelqu'un appelle notifie (tous) () Ensuite, le thread inactif recommence à s'exécuter dans le bloc synchronisé, mais est traité de manière égale avec tous les autres threads qui le souhaitent. Un seul en quelque sorte choisi (le programmeur ne peut pas influencer ni dépendre de celui-là) y parvient réellement.

1
Alpedar

Mot clé synchronisé en Java est utilisé pour 2 choses.

La première signification est ce que l'on appelle la section critique, c'est-à-dire une partie du code accessible simultanément par un thread. L'objet que vous passez à synchronized permet une sorte de dénomination: si un code est exécuté dans synchronized(a) il ne peut pas accéder à un autre bloc qui est dans synchronized(a) mais peut accéder au bloc de code dans synchronized(b).

Un autre problème est la communication entre les threads. Le thread peut attendre jusqu'à ce qu'un autre thread le notifie. L'attente et la notification doivent être écrites dans le bloc synchronized.

C'était une très courte description. Je vous suggère de rechercher un didacticiel sur le multithreading et de le lire.

1
AlexR

Le mot clé synchronisé, ainsi que les opérations d'attente et de notification forment un moniteur de condition non bloquante , une construction utile pour coordonner plusieurs threads.

0
Atreys