Home > front end >  In Java how to synchronize cache read and write operations
In Java how to synchronize cache read and write operations

Time:04-23

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.

CodePudding user response:

You could achieve this by using the ReadWriteLock interface implemented with a ReentrantReadWriteLock instance. This class can represent your case of read and write by acquiring the corresponding lock when performing the getIds and loadIds operations. In fact,

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.

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReadWriteLock.html

Basically, your loadIds should acquire the write-lock before proceeding with its operations. If it succeeds, it immediately acquires the lock and carries on with its computation; otherwise it blocks the corresponding thread until the lock is obtained or an InterruptedException is thrown.

On the other hand, the getIds method should acquire the read-lock instead. Where the current thread immediately obtains the lock if this is available; otherwise it 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;
    }
}
  • Related