猿问

简单的基于Java名称的锁?

MySQL具有方便的功能:


SELECT GET_LOCK("SomeName")

这可用于为应用程序创建简单的但非常特定的基于名称的锁。但是,它需要数据库连接。


我有很多情况,例如:


someMethod() {

    // do stuff to user A for their data for feature X

}

简单地同步此方法是没有意义的,因为,例如,如果在此期间同时为用户B调用此方法,则用户B无需等待用户A完成操作就可以开始操作,而只需为用户进行操作A和功能X的组合需要等待。


使用MySql锁,我可以执行以下操作:


someMethod() {

    executeQuery("SELECT GET_LOCK('userA-featureX')")

    // only locked for user A for their data for feature X

    executeQuery("SELECT RELEASE_LOCK('userA-featureX')")

}

由于Java锁定基于对象,因此似乎需要创建一个新对象来表示此锁定的情况,然后将其放置在某个位置的静态缓存中,以便所有线程都可以看到它。随后针对该情况进行锁定的请求将随后在高速缓存中定位锁定对象并获取其锁定。我试图创建类似这样的东西,但是锁缓存本身需要同步。另外,很难检测何时不再使用锁定对象,以便可以将其从缓存中删除。


我已经看过Java并发包,但是没有什么能够处理这样的事情了。有没有简单的方法可以实现此目的,还是我从错误的角度看待这个问题?


编辑:


为了明确起见,我不希望提前创建预定义的锁池,而是希望根据需要创建它们。我在想的一些伪代码是:


LockManager.acquireLock(String name) {

    Lock lock;  


    synchronized (map) {

        lock = map.get(name);


        // doesn't exist yet - create and store

        if(lock == null) {

            lock = new Lock();

            map.put(name, lock);

        }

    }


    lock.lock();

}


LockManager.releaseLock(String name) {

    // unlock

    // if this was the last hold on the lock, remove it from the cache

}


呼如林
浏览 441回答 3
3回答

一只萌萌小番薯

你可以有Map<String, java.util.concurrent.Lock>吗?每次需要锁定时,您基本上都会呼叫map.get(lockName).lock()。这是使用Google Guava的示例:Map<String, Lock> lockMap = new MapMaker().makeComputingMap(new Function<String, Lock>() {&nbsp; @Override public Lock apply(String input) {&nbsp; &nbsp; return new ReentrantLock();&nbsp; }});然后,如果需要,lockMap.get("anyOldString")将导致创建新的锁并将其返回给您。然后,您可以调用该锁。返回一个线程安全的Map,因此您可以与所有线程共享该Map。lock()makeComputingMap
随时随地看视频慕课网APP

相关分类

Java
我要回答