Je cherche un type de serrure où le fil qui tient le verrou peut le passer sur un autre fil de son choix.Serrure pouvant être transférée d'un fil à l'autre
Voici pourquoi je veux:
- J'ai une classe similaire à
ConcurrentHashMap
- une collection spécialisée qui est divisée en plusieurs segments - La plupart des modifications nécessitent qu'un seul segment à verrouiller. Quelques-uns nécessitent le verrouillage de deux segments (en particulier, la modification d'une clé pour qu'elle passe d'un segment à un autre).
- La plupart des lectures ne nécessitent pas de verrouillage: une lecture volatile est généralement suffisante, mais une recherche doit parfois verrouiller segments à la fois, si une vérification modification comptage ne
- Recherche se fait dans plusieurs threads (via un
ThreadPoolExecutor
) - il est essentiel que la fonction de recherche a une vue cohérente de tous les segments (par exemple, il ne doit pas manquer une entrée alors qu'il est déplacé d'un segment à un autre.)
- La tâche de recherche (pour un seul segment) peut être interrompue à tout moment.
Maintenant, je considère la situation où la méthode de recherche a été appelée dans le thread principal et découvre qu'il doit verrouiller tous les segments. Tous les verrous de segment doivent être tenus en même temps par le thread principal (pour s'assurer qu'il n'y a pas d'interférence) mais ce n'est pas le thread principal qui fera les mises à jour - c'est l'un des threads de travail. Par conséquent, j'essaie de faire passer le fil principal sur les verrous une fois qu'il sait qu'il a un cliché cohérent.
Nous avions l'habitude d'utiliser un seul verrou pour toute la collection, mais à mesure qu'il grossissait, il y avait trop de contention et une latence inacceptable pour les petites mises à jour. Déverrouiller et re-verrouiller (sur un ReentrantLock
) n'est pas sûr - un autre thread peut modifier le segment avant que le thread de travail commence la recherche.
Un plaine Semaphore
peut gérer le verrouillage et le déverrouillage par différents filetages. Le problème qui se pose alors est de savoir qui doit libérer le sémaphore - le thread de travail a besoin d'un moyen de signaler qu'il a pris possession du verrou (car il peut lancer une exception avant ou après ce point et le thread principal doit savoir s'il doit nettoyer up.) Il serait également difficile d'effectuer un test d'unité car on ne sait jamais si un sémaphore a été acquis ou publié dans le bon thread.
Ce serait un bonus si le verrou pourrait être utilisé rentrante dans d'autres méthodes (où il ne se transmet pas entre les threads).
J'imagine une combinaison d'un Semaphore
et un AtomicBoolean
ou AtomicReference
est appelé, mais une recherche rapide sur google n'a révélé aucun exemple. Y a-t-il une raison pour laquelle cette approche ne devrait pas être utilisée?
La concurrence fonctionne mieux avec un modèle simple. Compte tenu de la longueur de votre description et de la complexité de votre modèle, je vous suggère de simplifier vos exigences. IMHO est beaucoup plus susceptible de travailler efficacement. La seule méthode que je connaisse qui réveille un thread spécifique est Unsafe.park() et Unsafe.unpark (Thread) mais je ne recommanderais pas de les utiliser directement. –
Si tout ce que vous voulez est un "verrou" qui peut être passé sur pourquoi ne pas utiliser un mécanisme de passage de jeton, avec chaque verrou de segment comme un jeton, avec lui étant littéralement transmis? Si le temps de recherche de la collection est assez long, ce jeton peut même être un fichier, le fichier agissant comme un verrou. Le thread principal peut simplement donner le "verrou" au thread de travail. – Fakrudeen
Est-il possible de modéliser ceci de manière verrouillée en ayant des structures persistantes avec des "mises à jour" associatives créant de nouvelles structures plutôt que de les modifier en place? Votre description est une solution plutôt que le problème sous-jacent que vous résolvez, il est donc difficile d'en suggérer un. –