Exemple de scénario:problème avec des collections synchronisées de Java lorsque vous faites égaux() dans l'ordre inverse de plusieurs threads
- Créer deux SynchronizedSets (s1 et s2)
- les passer à deux fils (T1 et T2)
- Démarrer les fils
exécution de T1(): temps (toujours) s1.equals (S2)
de course de T2(): while (pour toujours) s2.equals (s1)
Qu'est-ce qui se passe? - les égaux de SynchronizedSet acquiert verrou sur lui-même
Il calcule la longueur du param qui est passé et aussi ce qu'il contient pour déterminer si c'est égal [Note: ceci est une estimation basée sur les journaux que j'analysé] Si le paramètre transmis est aussi un SynchronizedSet, les appels à size() et containAll() impliquent un verrou de ce qui doit également être acquis.
Dans l'exemple ci-dessus, blocage de l'acquisition des commandes de T1 et T2 sont les suivantes:
T1: s1 -> s2 T2: s2 -> s1
Ofc, elle conduit à une impasse.
Ce problème n'est pas spécifique aux collections synchronisées uniquement. Cela peut arriver même avec Hashtable ou Vector. Je crois qu'il s'agit d'une limitation Java API (conception). Comment surmonter cela? Comment puis-je m'assurer que cela ne se produise pas dans ma demande? Y a-t-il un principe de conception que je devrais suivre sans entrer dans cette situation?
@Tom: mais notez que vous pouvez toujours avoir des ennuis avec un verrou maître si vous n'acquérez pas les verrous subsidiaires en même temps. Par exemple, un blocage est possible si un thread qui détient déjà le verrou 's2' exécute le premier de vos extraits de code ... –
@Tom: en fait, je pense que votre premier extrait manquait de mon point. J'essayais de dire que l'un des moyens de garantir qu'il n'y a pas d'interblocage est d'utiliser un et un seul verrou pour toutes les structures de données. Bien sûr, c'est impraticable parce que (pour commencer) ça ne va pas. –
Si un thread détient déjà un verrou et appelle un code aléatoire, il est quand même en difficulté. Je suppose que vous pourriez le coder si vous utilisiez 'java.util.concurrent.locks', mais j'essaierais de coder quelque chose de beaucoup plus sensé. –