2010-07-09 34 views
2

Je développe pour Android 2.2, et un peu confus quant à la façon dont fonctionne ReentrantLocks. Le code suivant peut-il jamais lancer une exception IllegalMonitorStateException? Je demande parce que je ne vois pas comment il peut - selon l'API, tryLock renvoie vrai si et seulement si le verrou est obtenu avec succès - mais parfois la commande unlock() le fait.ReentrantLock Exceptions

public void lockDemo() { 
    ReentrantLock myLock = new ReentrantLock(); 
    if (myLock.tryLock()) { 
     System.out.println("Lock obtained"); 
     myLock.unlock(); 
    } 
} 
+0

L'exemple ne doit pas échouer. Mais votre code actuel est-il vraiment aussi simple? – mdma

+0

Oui et non. Le programme global est un peu plus grand, et a environ 8 threads en cours d'exécution et de partage d'informations. Mais le code à l'intérieur du bloc tryLock() est à peu près aussi simple. Je suis soit en train de copier des primitives vers des variables locales pour les manipuler plus tard, certaines opérations mathématiques, ou d'écrire dans un printWriter. Pour autant que je sache, il n'y a rien qui pourrait gâcher le ReentrantLock. – SirBoss

Répondre

0

Il pourrait ne pas réellement résoudre votre problème, mais il y a une discussion de quelque chose de similaire ici: http://www.jroller.com/ethdsy/entry/reentrantlock_bug

+0

Merci pour le lien. Comme tu l'as dit, je ne pense pas que la solution soit applicable à mon code, mais au moins maintenant je sais que je ne suis pas folle. – SirBoss

0

Le tryLock() mothod prend deux paramètres, long timeout, TimeUnit unit. Cela pourrait avoir quelque chose à voir avec ça. Je ne dis pas que cette façon d'utiliser les verrous est mauvaise, je ne les ai jamais utilisés de cette façon. Je l'ai appris à utiliser des serrures de cette façon:

public void lockDemo() { 
    ReentrantLock myLock = new ReentrantLock(); 
    try { 
     myLock.lock(); 
     // do work... 
    } catch (Exception e) { 
     // catch if something fails 
    } finally { 
     myLock.unlock(); 
    } 
} 
+0

Il y a aussi un tryLock() qui ne prend pas d'arguments - il renvoie juste false immédiatement si le verrou est indisponible. Cependant, je n'ai pas vu beaucoup d'exemples de code officiel qui l'utilisent. http://developer.android.com/reference/java/util/concurrent/locks/ReentrantLock.html#tryLock() – SirBoss

1

De la javadoc: unlock() lancers francs IllegalMonitorStateException si le thread courant ne tient pas la serrure. Je suppose que vous ne poseriez pas à moins que vous voyiez ceci, mais, vous devriez vérifier la trace de pile pour voir quelle méthode la déclenche. L'exemple que vous donnez ne reproduira pas cette situation, donc votre code réel doit être plus complexe et le problème doit se situer quelque part dans les autres bits. Au-dessus de ma tête, j'imagine que le verrou est peut-être en train d'être déverrouillé deux fois d'une façon ou d'une autre. Ou que le verrou ne peut pas être effectivement acquis dans certains chemins de code qui pensent qu'ils ont le verrou.

+0

Je suis d'accord avec votre évaluation, mais je n'ai absolument aucune idée de l'autre code que je pourrais écrire ferait que cela arrive. AFAIK, Si un autre thread détient le verrou, ce fil ne peut pas l'obtenir; Si ce thread détient le verrou, il devrait être capable de le libérer. À moins que je ne manque quelque chose? – SirBoss

+0

C'est vrai, mais peut-être qu'il est sorti deux fois? Peut-être que c'est déverrouillé sans tenir la serrure en quelque sorte? Ces scénarios. Une minute avec un débogueur suivi des appels aux méthodes sur ce verrou devrait le montrer. –