La soluzione più semplice è quello di ottenere una fotografia istantanea ogni volta,
list = get snapshot
{
work on the list
}
discard list // GC it
poiché l'istantanea è una struttura di dati congelato costante, client può accedere liberamente.
Ma se il client accede a una struttura dati che può essere modificata da un'altra parte, diventa problematico.Dimentica i problemi di concorrenza; pensare la semantica del codice seguente
{
n = list.size();
list.get(n-1);
}
get(n-1)
può fallire, perché l'elenco potrebbe essere ridotto quando si chiama.
avere un qualche tipo di garanzia di coerenza, il lato client deve fornire demarcazioni transazione esplicita durante la sessione di accesso, come
acquire lock // preferably a read-lock
{
work on the list
}
release lock
Si noti che questo codice non è più semplice rispetto alla soluzione istantanea. E il cliente può ancora "perdere" gli aggiornamenti, proprio come la soluzione istantanea.
E si deve decidere se si desidera forzare i codici client a eseguire questo tipo di blocco.
Ovviamente non è privo di meriti; può essere migliore nelle prestazioni rispetto alla soluzione snapshot se l'elenco è grande e gli aggiornamenti non sono frequenti.
Se questo approccio è più appropriato per l'applicazione, possiamo progettare qualcosa di simile
interface CloseableList extends List, Closeable {}
public CloseableList readProducts() // acquire read-lock when called
-- client code
try{CloseableList list = readProducts())
{
....
}
// on close(), release the read-lock
Se il cliente ha solo bisogno di iterare i prodotti, siamo in grado di utilizzare java8 flusso
final ReadWriteLock lock = ...
private ArrayList productList = new ArrayList();
// modifications to `productList` must be protected by write lock
// javadoc: reader must close the stream!
public Stream readProducts()
{
lock.readLock().lock();
return productList.stream().onClose(lock.readLock()::unlock);
}
-- client code
try(Stream products = readProducts())
{
...
}
Possiamo anche progettare l'API per prendere il codice cliente in modo da poterlo circondare con protezioni
public void readProducts(Consumer<List> action)
{
lock read
action.accept(productList);
finally unlock read
}
-- client code
readProducts(list->
{
...
});
Ricerca correlata ione: http://stackoverflow.com/questions/35281056/how-to-synchronize-unmodifiable-collections –