J'utilise dans mon code en ce moment un ReentrantReadWriteLock pour synchroniser l'accès sur une structure en arbre. Cette structure est grande, et lu par de nombreux fils à la fois avec parfois des modifications de petites pièces de ce - de sorte qu'il semble correspondre à la lecture-écriture de l'idiome. Je comprends que cette classe particulière, on ne peut pas élever un verrou en lecture à un verrou d'écriture, ainsi que par les Javadocs on doit libérer le verrou de lecture avant d'obtenir le verrou d'écriture. J'ai utilisé ce modèle avec succès dans non réentrant des contextes avant de.
Ce que je suis la recherche cependant, c'est que je ne peut pas de manière fiable acquérir le verrou d'écriture sans bloquer pour toujours. Depuis le verrou en lecture est réentrant et je suis en train de l'utiliser en tant que tel, le code simple
lock.getReadLock().unlock();
lock.getWriteLock().lock()
peut bloquer si j'ai acquis la readlock reentrantly. Chaque appel à débloquer réduit simplement la tenir compte, et que le verrou n'est libéré lorsque le tenir compte atteint zéro.
EDIT pour préciser cela, car je ne pense pas que je vous l'explique trop bien au début - je suis conscient qu'il n'est pas intégré dans l'escalade de verrous dans cette classe, et que je dois il suffit de relâcher le verrou de lecture et d'obtenir le verrou d'écriture. Mon problème est que, indépendamment de ce que les autres threads sont en train de faire, en appelant getReadLock().unlock()
peut pas réellement la libération de ce thread sur la serrure si elle a acquis il reentrantly, auquel cas l'appel à getWriteLock().lock()
bloquera jamais que ce fil a encore une emprise sur le verrou en lecture et donc des blocs de lui-même.
Par exemple, cet extrait de code n'atteindra jamais la println déclaration, même lorsqu'il est exécuté single thread n'ayant pas d'autres threads d'accéder à la serrure:
final ReadWriteLock lock = new ReentrantReadWriteLock();
lock.getReadLock().lock();
// In real code we would go call other methods that end up calling back and
// thus locking again
lock.getReadLock().lock();
// Now we do some stuff and realise we need to write so try to escalate the
// lock as per the Javadocs and the above description
lock.getReadLock().unlock(); // Does not actually release the lock
lock.getWriteLock().lock(); // Blocks as some thread (this one!) holds read lock
System.out.println("Will never get here");
Alors je vous le demande, est-il un bel idiome pour gérer cette situation? Plus précisément, lorsqu'un thread qui détient un verrou en lecture (éventuellement reentrantly) découvre qu'il a besoin de faire un peu de l'écriture, et donc veut "suspendre" son propre verrou en lecture afin de ramasser le verrou d'écriture (blocage que nécessaire sur d'autres threads pour libérer leurs cales sur le verrou en lecture), et puis "pick up" de son emprise sur le verrou en lecture dans le même état après?
Depuis cette ReadWriteLock mise en œuvre a été spécifiquement conçu pour être réentrant, il y a sûrement une façon logique d'élever un verrou en lecture à un verrou en écriture lorsque les verrous peuvent être acquises reentrantly? C'est la partie critique que signifie l'approche naïve ne fonctionne pas.