I am working on implementing a simple cache using ArrayList in my application.
I would like to synchronize cache update operations, while updating the cache I should not allow to perform read operations. So once cache update is completed, then only cache should allow to read.
ContextManager.java
public class ContextManager{
private List<String> trashCanIds;
public List<String> getIds() {
return ids;
}
public void setIds(List<String> ids) {
this.ids = ids;
}
}
ConfigManager.java
public class ConfigManager{
ContextManager ctxManager = new ContextManager();
public synchronized List<String> loadIds() throws Exception {
Utils utils = new Utils();
List<String> listIds = null;
String[] ids = utils.fetchIds();
if(Objects.nonNull(ids) && ids.length > 0) {
listIds = new ArrayList<>(Arrays.asList(ids[0].split(",")));
}
ctxManager.setIds(idsList);
return idsList;
}
}
DeleteManager.java
public class DeleteManager {
ConfigManager configManager = new ConfigManager();
configManager.loadIds();
}
TestManager.java
public class TestManager {
ContextManager contextManager = new ContextManager();
contextManager.getIds();
}
In this code I have synchronized the loadIds() method.
Need help, how to prevent reading getIds() while loadIds() in progress.
You could achieve your goal by using the ReadWriteLock
interface. Specifically, the ReentrantReadWriteLock
implementation. This class can handle your read and write cases by acquiring the corresponding lock when performing the getIds
and loadIds
operations.
A ReadWriteLock maintains a pair of associated locks, one for read-only operations and one for writing. The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.
Basically, loadIds
should acquire the write-lock before proceeding with its operations. If it succeeds, it immediately acquires the lock, and then carries on with its computation. If not, the method blocks the corresponding thread until the lock is obtained or an InterruptedException
is thrown.
Conversely, the getIds
method should acquire the read-lock. In this scenario, if the lock is available, the current thread obtains the lock and moves on. Otherwise, the method blocks the corresponding thread until the lock is obtained or an InterruptedException
is thrown.
ContextManager.java
public class ContextManager{
private List<String> trashCanIds;
private ReadWriteLock lock;
private Lock readLock;
private Lock writeLock;
public ContextManager(){
lock = new ReentrantReadWriteLock(true);
readLock = lock.readLock();
writeLock = lock.writeLock();
}
public List<String> getIds() {
readLock.lock();
try {
List<String> tempTrashCanIds = new ArrayList(trashCanIds);
} finally {
readLock.unlock();
}
return tempTrashCanIds;
}
public void setIds(List<String> ids) {
this.ids = ids;
}
public void readLock(){
this.readLock.lock();
}
public void readUnlock(){
this.readLock.unlock();
}
public void writeLock(){
this.writeLock.lock();
}
public void writeUnlock(){
this.writeLock.unlock();
}
}
ConfigManager.java
public class ConfigManager{
ContextManager ctxManager = new ContextManager();
public List<String> loadIds() throws Exception {
Utils utils = new Utils();
List<String> listIds = null;
String[] ids = utils.fetchIds();
if(Objects.nonNull(ids) && ids.length > 0) {
listIds = new ArrayList<>(Arrays.asList(ids[0].split(",")));
}
ctxManager.writeLock();
try {
ctxManager.setIds(idsList);
} finally {
ctxManager.writeUnlock();
}
return idsList;
}
}