Managing multiple locks

前端 未结 2 1023
庸人自扰
庸人自扰 2021-01-16 06:07

I have the following situation: I\'m concurrently processing requests that have a given key. I can process any number of requests at the same time, as long as each key in pr

相关标签:
2条回答
  • 2021-01-16 06:45

    How about this:

    create a ConcurrentHashMap<K,Semaphore>

    ConcurrentMap<K, Semaphore> myMap = new ConcurrentHashMap<>();

    in your doSomething() method, use the putIfAbsent() method to of your map to add a semaphore with one permit to the map, only if the key does not exist in the map.

    subsequently do a get() on the key to fetch the semaphore for that key, and then do your stuff. Release the semaphore when done.

    void doSomething(K key) {
         myMap.putIfAbsent(key, new Semaphore(1));
         Semaphore s = myMap.get(myKey);
         s.aquire();
         try {
         // do stuff
         } finally {
           s.release();
         }
     }
    

    The only real problem with this scheme is if your list of keys will grow indefinitely, I don't have a good race-condition-free strategy for removing the semaphore from the map. (But if you know you will reuse the same keys over and over, or the list will grow slowly, then maybe this is ok.)

    0 讨论(0)
  • 2021-01-16 06:52

    Following solution does not locks LockMap and so is extremly parallel. It uses custom-made Locks to track the moment when they can be deleted, and handles concurrent deletion/creation.

    class Lock {
        boolean busy=true; // locked state, a thread is working
        int waitCount=0; // number of waiting threads
    
            /** returns true if lock succeeded */
        synchronized boolean tryLock() throws InterruptedException {
            if (busy) {
                waitCount++; 
            } else if (waitCount==0){
                    // such values mean that the lock is deleted
                return false;
            } else {
                busy=true;
                return true;
            }
            for (;;) {
                wait();
                if (!busy) {
                    waitCount--;
                    busy=true;
                    return true;
                }
            }
        }
    
    }
    
    class LockMap<K> {
        private ConcurrentHashMap<K, Lock> locks = new ConcurrentHashMap<>();
    
        void acquireLock(K key) throws InterruptedException {
            for (;;) {
                Lock lockObj = locks.get(key);
                if (lockObj==null) {
                    Lock myLockObj = new Lock();
                    lockObj=locks.putIfAbsent(key, myLockObj);
                    if (lockObj==null) {
                        // successfully inserted, and so locked
                        return;
                    }
                }
                // lockObj existed, lock it or wait in queue
                if (lockObj.tryLock()) {
                    return;
                }
            }
        }
    
        void releaseLock(K key) {
            Lock lockObj = locks.get(key);
            synchronized (lockObj) {
                lockObj.busy=false;
                if (lockObj.waitCount==0) {
                    locks.remove(key);
                } else {
                    lockObj.notify();
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题