Comment puis-je interrompre une déclaration synchronisée en Java?
-
21-09-2019 - |
Question
J'ai deux fils qui veulent synchonize sur le même objet. Thead A
doit être en mesure d'interrompre la discussion B
si une certaine condition a été fullfilled. Voici quelques pseudo-code de ce que les deux threads ne / devraient faire.
A:
public void run()
{
while(true)
{
//Do stuff
synchronized(shared)
{
//Do more stuff
if(condition)
{
B.interrupt();
}
}
}
}
B:
public void run()
{
while(true)
{
try
{
//Do stuff
synchronized(shared)
{
//Do more stuff
}
}
catch(InterruptedException e)
{
continue;
}
}
}
Voici la situation que je ne peux pas résoudre:
- Discussion
A
saisit la ressource partagée et fait des choses. - Pendant ce temps, le fil
B
atteint le bloc synchronisé, et attend pourA
de libérer sa ressource partagée. - Discussion
A
, tout en faisant des choses, réalisé que le thread B ne devrait pas avoir la ressource partagée, et tente d'interrompre la discussionB
. Mais cette discussionB
a déjà dépassé les points où pourrait être jeté unInterruptedException
.
Ma question est, est-il un moyen d'interrompre un fil alors qu'il est en attente d'être synchronized
sur quelque chose?
La solution
Pour ce genre de chose, vous devez utiliser les classes dans java.util.concurrent.locks
-. ils ont beaucoup plus de fonctionnalités, y compris les serrures interrompues
Edit:. Si vous ne pouvez pas utiliser ces classes, puis regardez la réponse de jkff - vos besoins peuvent être satisfaits avec le mechnism wait()
/ de notify()
, mais il est facile d'introduire des bugs subtils
Autres conseils
En effet, vous devez utiliser les serrures ou mettre en œuvre vos trucs avec les Object.wait()
, Object.notify()
et méthodes Object.notifyAll()
(serrures sont effectivement mises en œuvre avec eux). Ne pas oublier de traiter les soi-disant « wakeups parasites » (wait()
peut revenir même si Noone appelé notify()
ou notifyAll()
, il devrait donc toujours être appelée dans une boucle qui vérifie que la condition que vous attendez est satisfaite).
Non, mais ReentrantLock.lockInterruptibly()
se comporte comme l'instruction monitorenter
primitive et peut être interrompue.