Je travaille sur une application pour le J2ME et parfois em> il gèle complètement em> et il faut assez de temps em> pour le SMS pour le fermer . Il me semble qu'un problème de verrouillage mort. P>
Pourriez-vous me conseiller sur ce qui pourrait causer des verrous morts? Serait, par exemple, appeler une méthode synchronisée d'un objet causer une serrure morte si elle appelle une autre méthode synchronisée à sa propre? P>
merci! p>
Ai-je raison de dire qu'une impasse est censée se produire dans le cas suivant: p>
objet Désolé si ça a l'air stupide de moi, probablement c'est. Mais c'est pourquoi em> je demande. Merci! P>
4 Réponses :
serait, par exemple, appeler une méthode synchronisée d'un objet entraîne une serrure morte si elle appelle une autre méthode synchronisée à sa propre? p>
Non, car
Synchronisé code> Les serrures en Java sont réentrant em>: vous pouvez acquérir le même verrou de la même thread plusieurs fois sans problème. P>
Une impasse se produit par exemple Lorsque le thread a tient la serrure L et tente d'acquérir le verrouillage M, tandis que le fil b contient le verrouillage M et tente d'acquérir la serrure L. Ainsi, les deux threads attendent une serrure détenue par l'autre et ne peuvent pas progresser pour libérer leur propre verrou. Cela provoque des deux threads d'attendre pour toujours. La situation peut également impliquer plus de 2 threads. P>
Deadlocks peut être très difficile à détecter, de sorte que la manière typique est d'essayer de éviter em> eux par une conception minutieuse. Le moyen le plus simple d'y parvenir est de garantir que tout fil qui doit acquérir plusieurs serrures, les acquiert toujours dans le même ordre mondial prédéfini. Par exemple. Si dans l'exemple ci-dessus, les threads A et B tentent d'acquérir la serrure L d'abord, puis verrouillez-la, il n'y aura pas d'impasse. P>
Votre problème peut également être causé par d'autres choses que celles-ci. Un Livelock em> (lorsqu'un thread, sans bloqué, ne peut toujours pas progresser car il continue de réessayer une opération qui échoue toujours). P>
Mise à jour: accéder au verrou de l'extérieur de l'objet h3>
avec des serrures intrinsèques Java (c.-à-d.
Synchronisée des blocs code> Synchronisés), l'objet sous-jacent
Lock code> n'est pas visible dans le code, seul l'objet que nous verrouillons . Considérez P>
class MyClass { private Object object = new Object(); public synchronized void synchronizedOnThis1() { ... } public void synchronizedOnThis2() { synchronized(this) { ... } } public void synchronizedOnPrivateObject() { synchronized(object) { ... } } } class ExternalParty { public void messUpLocks() { final MyClass myObject = new MyClass(); synchronized(myObject) { Thread otherThread = new Thread() { public void run() { myObject.synchronizedOnThis1(); } }; otherThread.start(); // do a lengthy calculation - this will block the other thread } } }
Voulez-vous dire que toutes les méthodes synchronisées d'un objet utiliseraient la même serrure afin qu'aucun verrou de mort ne soit possible pour survenir?
@Albus, déclarant une méthode synchronisée code> équivaut à joindre le contenu de la méthode dans un
synchronisé (this) code> bloc. C'est à dire. Toutes les méthodes d'instance code> Synchronisées sont synchronisées sur la même instance de classe, aucune impasse n'est possible. À moins que, bien sûr, une autre personne en dehors de l'objet se verrouille sur le même objet.
"Sauf si, bien sûr, une autre personne en dehors de l'objet se verrouille sur le même objet." Eh bien, on ne peut pas faire cela si l'objet code> verrouillé code> n'est pas exposé manuellement par moi, peut-on un ?! C'est-à-dire que si toute la synchronisation est faite par des méthodes synchronisées, il n'y a pas de danger ce type?
@Albus: Non, ce n'est pas le cas - "Quelqu'un d'autre en dehors de l'objet verrouille sur le même objet" signifie une personne en dehors d'un myClass code> MODY appels
myClass FOO = nouveau myClass (); ... synchronisé (foo) {...} code>
Merci beaucoup! Donc, diriez-vous que l'utilisation d'objets privés comme une serrure serait une approche plus sûre que le synchronisé (this) code> un? Si oui, serait-ce une préoccupation de conception, si je synchrais toujours toute la source de la méthode car il y a beaucoup de choses à mettre à jour?
@Albus, il est théoriquement plus sûr, bien que cela rend le code un peu plus compliqué. Le code bien écrit ne devrait pas contenir de tels serrures problématiques, c'est donc plus une question de style (ou paranoïa :-) le seul cas où j'utiliserais certainement cet idiome est une bibliothèque publique où je n'ai aucun contrôle sur le code client.
@Albus, lors de la synchronisation de l'ensemble du corps de la méthode, la plus grande préoccupation est de la durée de l'exécution. Les serrures de longue date augmentent les chances de filtrait de fil et peuvent donc ralentir l'exécution de manière significative, pour le moins. S'il faut utiliser un synchronisé (someObject) code> bloc ou un
Synchronisé code> est une préoccupation mineure pour moi dans ce contexte.
Eh bien, les deux dernières réponses sont en fait assez évidentes, quand je viendrai penser, mais pour eux, je me sens plus confiant dans ma pensée. Merci! Même si je ne peux toujours pas signaler le problème: j'ai un Canvas CODE> et les événements externes l'accédent via des méthodes synchronisées de cette toile. Donc, après tout dit, il ne peut pas être éventuellement i> une impasse, non?
@Albus, si vous n'avez qu'une seule serrure dans le jeu, il ne peut pas y avoir de blocage. Notez toutefois que des serrures cachées peuvent être impliquées dans les appels de bibliothèque, en particulier lorsque l'interface graphique est impliquée. Je ne sais pas J2ME donc je ne peux rien dire de rien spécifique à ce sujet. Je vous suggère d'ouvrir une nouvelle question et de montrer la partie pertinente de votre code - il y a sûrement des experts J2ME ici :-)
La raison la plus probable serait deux threads essayant d'obtenir des serrures à deux objets. Le fil 1 verrouille A et attend que B, mais filetez 2 verrouillons B et attendez A. Les deux threads finissent par attendre pour toujours pour des objets qui ne seront jamais libérés. p>
Il n'y a pas de solution rapide, sauf que votre code fait des choses dans un ordre très bien défini. En règle générale, le bloc synchronisé doit être aussi petit que possible, généralement sur un objet spécifique que sur une méthode. Mettez beaucoup de journalisation et voyez si vous pouvez déterminer si quelque chose comme ça se passe. p>
Java 5 a des objets de verrouillage explicites qui permettent un contrôle grain fini comprenant des délais d'attente sur des blocs synchronisés simples, mais je ne sais pas s'ils seraient utiles pour J2ME. Il existe une backport des libs de la concurrence Java 5 qu'il peut être possible de travailler avec J2ME - http: // Backport-jsr166.sourceforge.net/ Si ce problème est suffisamment important pour le mériter. P>
Oui merci! J'espère que ça ne va pas arriver à cela. Après tout, le bon et le code simple est toujours la meilleure solution.
quand est-ce que l'impasse se produit? strong> p> Utilisation excessive de la synchronisation avec une commande de verrouillage incohérent provoque une impasse. P>
solution pour éviter la serrure morte forte> p> blockquote>
maintenir la commande et utiliser moins de synchronisation. p>
Ce qui suit est un scénario, ce qui fait une impasse. p>
xxx pré> si la méthode1 () et Méthode2 () Les deux seront appelés par deux ou plusieurs threads, il y a une bonne chance d'impasse, car si THEAD 1 Aquièmes verrouillez-la sur l'objet STIFIER pendant l'exécution de la méthode1 () et le thread 2 acquiert un verrouillage sur un objet entier tout en exécutant la méthode2 () Les deux attendront à libérer le verrouillage de l'entier et de la chaîne pour procéder plus loin, ce qui n'arrivera jamais. P>
Si vous avez l'air au-dessus du code, vous avez peut-être pu comprendre que la vraie raison de l'impasse n'est pas plusieurs threads. Mais la façon dont ils accèdent le verrouillage, si vous fournissez un accès commandé, le problème sera résolu, voici la version fixe. p>
xxx pré> Il n'y aurait pas de blocage car les deux méthodes Est accessible à une serrure sur l'objet Entier et String dans le même ordre. Donc, si le thread a acquis une serrure sur un objet entier, le thread b ne procédera pas avant que le filetage A reporte une serrure entier, le filetage A de même manière que si le thread b ne conserve pas la verrou de chaîne, car maintenant le thread B ne vous attendez pas à un verrouillage entier. Pour continuer davantage. p>
courtoisie p> blockquote>