Eu tenho uma coleção. Muitas threads devem ser capazes de ler dela ao mesmo tempo, mas apenas uma thread deve ser capaz de escrever nela por vez, e somente quando não estiver sendo lida. O ReentrantReadWriteLock do Java parece perfeito para isso.
No entanto, estou confuso sobre como escrever o iterador para a coleção. O iterador deve obter o bloqueio de leitura quando ele começa. Mas não consigo descobrir como garantir que ele será desbloqueado no caso em que o iterador nunca terminou.
Aqui está um exemplo de código que é apenas um wrapper em torno de um iterador normal que bloqueia e desbloqueia:
import java.util.Iterator;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
public class ReadLockIterator<T> implements Iterator<T> {
private final Lock lock;
private final Iterator<T> iterator;
public ReadLockIterator(ReadWriteLock lock, Iterator<T> iterator) {
this.lock = lock.readLock();
this.iterator = iterator;
this.lock.lock();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public T next() {
try {
return iterator.next();
}
finally {
if(!hasNext())
lock.unlock();
}
}
}
Isso funcionará bem, desde que o usuário obtenha todos os elementos do iterador. Mas o que acontece se o usuário não fizer isso? Como posso garantir que o bloqueio será eventualmente liberado, mesmo que alguns elementos nunca sejam lidos do iterador?
Meu primeiro pensamento foi colocar uma segunda verificação no finalize()
método do iterador, mas então li que finalize não deve ser usado para desbloquear.
Qual é a melhor maneira de lidar com isso?