Java blocs synchronisés
Si nous avons une méthode:
public void doSomething(){
synchronized(this){
//some code processing here
}
String temp = "init"; //instead of i++
synchronized(this){
//some other code processing here
}
}
Cette méthode est équivalente à public synchronized void doSomething()
?
Est-il une raison pas de supposer que le planificateur de threads dans certaines exécutions, pas résultat dans le même flux que la synchronisation de l'ensemble de la fonction? Qui est:
- Thread1 entre la première synchronisation de bloc.
- Thread2 blocs.
- Thread1 continue avec
i++
et se déplace à la deuxième bloc synchronisé tout en Thread2 reste bloqué. - Comme un résultat, Thread2 entre la méthode après Thread1 a quitté les deux blocs synchronisés.
Tous j'ai besoin de savoir, c'est:
- Puis-je compter sur tous les contextes d'exécution que les deux threads (Thread1 et Thread2) peut être dans la méthode en même temps? Par exemple, Thread2 dans la première synchronisation de bloc et Thread1 dans la seconde synchronisation de bloc pour atteindre la simultanéité.
- Une exécution de flux, où un seul thread va être dans la méthode (à un moment) de la sérialisation de l'ensemble des flux, ce qui équivaut à
public synchronized void doSomething()
?
Pourriez voulez mettre à jour votre corps post pour refléter votre déménagement de
Code mis à jour comme demandé
i++
.Code mis à jour comme demandé
OriginalL'auteur Cratylus | 2010-08-04
Vous devez vous connecter pour publier un commentaire.
Dans certains exécutions, il aurait le même débit que la synchronisation de l'ensemble des fonctions, bien sûr - mais pour être vraiment équivalent à ce qui rend la méthode synchronisée, elle devrait avoir le même débit pour tous exécutions.
Comme il est, il y a une possibilité qu'un autre thread va saisir le verrou (que ce soit pour cette méthode ou une autre code de verrouillage sur le même écran) à mi-parcours de l'exécution. Qui ne pourrait pas se produire si la méthode elle-même ont été synchronisés, par conséquent, ils ne sont pas équivalentes.
(En aparté, le verrouillage de
this
est généralement considéré comme une mauvaise pratique de toute façon; je ne me souviens pas la dernière fois que j'ai écrit une méthode synchronisée. Je lock du secteur privé moniteurs au lieu de cela, de sorte que je sais que mon code est le seul code qui peut verrouiller sur eux).EDIT: pour répondre À votre edit:
Absolument pas! Il est garanti que vous ne ont deux fils à la fois en parallèle, un bloc synchronisé sur le même écran.
Vous avez trois sections de code: la première synchronisation de bloc, la désynchronisation, et le second synchronisé partie.
N'importe quel nombre de threads peut être en cours d'exécution dans la désynchronisation partie à la fois. Pour un exemple (parce que vous êtes la synchronisation sur les
this
), un seul thread peut s'exécuter soit de la synchronisation des blocs. Si vous voulez parvenir à la concurrence, vous devez synchroniser sur différents moniteurs.En outre, il semble que vous voulez et les garanties de l'planificateur de laisser un autre thread saisir le verrou si elle a été en attente pour elle. Je ne crois pas qu'il y a une telle garantie - un thread exécutant le premier bloc pourrait la libérer, mais continuer dans la même timeslice et acquérir de nouveau avant que tous les autres threads obtenu dans. Dans certaines machines virtuelles qui ne peut pas arriver, mais je ne crois pas qu'il n'y a aucune garantie autour d'elle.
Tout ce que je besoin de savoir, c'est si je peux compter sur tous les contextes d'exécution que les deux threads (par exemple Thread1 et Thread2) peut être dans la méthode, dans le même temps, l'e.g thread2 dans la première synchronisation de bloc et thread1 dans la seconde synchronisation de bloc pour atteindre la simultanéité, ou il y aura quelques exécution de flux où seulement 1 thread va être dans la méthode efficacement la sérialisation de l'ensemble des flux de rendre l'équivalent de public synchronized void doSomething()
J'ai édité ma réponse en conséquence.
OriginalL'auteur Jon Skeet
Non, il n'est pas. Par exemple, pour le code ci-dessus
Thread on entre dans la première synchronisés bloc s'exécute et quitte ensuite est mis à l'écart.
Fil deux entre le premier synchronisés bloc de l'exécute par incréments je pénètre alors dans la deuxième synchronisés bloc avant d'être mis à l'écart.
Fil-en un maintenant ne peut pas continuer jusqu'à ce Thread deux sorties de la deuxième synchronisés bloc.
Ce modèle ne peut pas se produire si l'ensemble de la méthode est synchronisés.
OriginalL'auteur Toby
Pas! Ce n'est jamais le cas. Il y a un seul verrou associé à
this
. En vertu de l'utilisation de la même serrure pour les deux blocs synchronisés, il est impossible pour Thread2 pour être dans la premièresynchronized
bloc si Thread1 est dans la deuxièmesynchronized
bloc.Toutes les autres réponses indiquant que la méthode que vous avez posté n'est pas la même que la synchronisation de l'ensemble de la méthode sont techniquement correctes.
Une méthode synchronisée obtient un verrou sur
this
. Supposons que la classe "Toto" contient synchronisées et non synchronisée méthodes. Si une instance de "Foo" est partagé entre les threads et un autre thread choisit de synchroniser sur cette instance, alors qu'aucun autre thread sera en mesure d'entrer méthodes synchronisées avec cette instance. La recommandation d'utiliser un bloc synchronisé avec un moniteur de verrouillage pour empêcher les autres de code à partir des sources de conflit en synchronisation sur cet objet.OriginalL'auteur Tim Bender
Étant donné que la synchronisation de mot-clé est utilisé pour mettre en œuvre les moniteurs en Java, le morceau de code ne peut pas être garanti pour être synchronisé.
Dans la réalité, est-il possible pour le fils en question pour terminer la première synchronisation de bloc, et ensuite exécuter l'instruction pour incrémenter la valeur de
i
, avant l'exécution du bloc suivant.Je suis en supposant que la variable
i
contient de l'état, qui est partagé entre les deux fils, auquel cas l'opération n'est pas thread-safe. Afin de rendre la séquence des opérations thread-safe, vous devez vous assurer que l'ensemble de la séquence est exécutée par un seul thread à la fois. L'exécution d'opérations individuelles dans des moniteurs distincts est aussi bon que l'exécution des opérations sans moniteur; l'ensemble de la séquence doit être gardé par le moniteur.Plus d'infos au artima.com dans le exemple de chapitre à partir de l'Intérieur de la Machine Virtuelle Java.
MODIFIER:
Compte tenu du fait que la question reflète désormais l'utilisation d'un local objet de type String, la séquence d'opérations peuvent être considérés comme des "thread-safe". Chaque thread crée son propre local de référence sur la pile à l'objet de type String; toute mutation de l'objet dans un thread, n'affectera pas les autres en raison de l'immuable de la propriété des objets String (un nouvel objet String est créé pour toutes fins pratiques, lorsque la mutation se produit, et, par conséquent, l'état n'est pas vraiment partagé entre les threads).
Accent:
Lors de la tentative de synchronisation de threads, tenir compte de la séquence des opérations pour être thread-safe si l'accès aux données partagées est fait mutuellement exclusifs; de cette manière, un thread ne sera pas en mesure de lire ou d'écrire les variables partagées, tandis que l'autre est d'effectuer une opération portant sur les données partagées. En utilisant seulement les variables locales, supprime tous les sens du partage entre les threads.
Non, il n'y a aucune garantie. Comme je l'ai indiqué dans la réponse, Thread1 et Thread2 pouvez quitter le premier moniteur (dans une séquence), et d'effectuer le fonctionnement sans surveillance (la déclaration de l'entre-deux blocs de synchronisation), avant que l'un d'eux entre dans le deuxième moniteur. Cela va à l'encontre de ce que vous voulez atteindre - deux fils sont à l'intérieur d'un moniteur ou d'un seul d'entre eux est l'exécution de la méthode.
OriginalL'auteur Vineet Reynolds
Non, il n'est pas équivalent à
synchronized void doSomething()
parce quei++
n'est pas une opération atomique. En fait, il n'a probablement quelque chose commeint temp = i; i = i + 1; result = temp
Si ces opérations ne sont pas prises atomique, alors la valeur de
i
on pouvait lire alors qu'il est dans un mauvais état.OriginalL'auteur Nate W.
Cette méthode n'est pas la même c'est une méthode synchronisée.
Le comportement qui explique peut-être vu, mais ne peut jamais être garantis.
OriginalL'auteur Gopi