1.场景
ktv,包间,订单
在ktv针对具体包间下单时,是需要加锁去实现的,不然有可能同一个包间同时产生2个订单
但是锁加在哪里?加在包间对象?NO!
因为“包间”对象从数据库里查询出来的,不是单实例的对象。
加在方法?或者代码块?NO!
如果加在方法或者代码块,会导致所有下单操作被阻塞,因为整个ktv所有影厅的下单代码是同一块
这也不行,那也不行,怎么办?有没有一种方法可以针对“包间”的id或name等唯一属性加锁?能!!!
2.基于ReentrantLock封装的字符串参数的锁
使用方式如下:
LockKey是一个String类型的,可以是id,name的一些对象的简单属性
ResourceLock.accquireWrite(LockKey);
...
...
ResourceLock.releaseWrite(LockKey);
实现代码如下:
SysnKeyLock.java:继承ReentrantLock
public class SysnKeyLock extends ReentrantLock { private static final long serialVersionUID = 1478211960393710925L; String key; public SysnKeyLock(String key) { this.key = key; } public String getKey() { return this.key; } public void setKey(String key) { this.key = key; } }SysnLockPool.java:维护一个HashTable,记录String-Lock的对应关系,cache记录已经创建过的对象
import java.util.Hashtable; import org.apache.commons.collections.map.LRUMap; public class SysnLockPool { private static final int poolSize = 10000; private Hashtable<String, SysnKeyLock> core = new Hashtable(); private LRUMap cache = new LRUMap(10000); public SysnLockPool() { } public synchronized SysnKeyLock getLock(String resourceID) { SysnKeyLock lock = (SysnKeyLock)this.core.get(resourceID); if(lock == null) { lock = (SysnKeyLock)this.cache.get(resourceID); if(lock == null) { lock = new SysnKeyLock(resourceID); } else { this.cache.remove(resourceID); } this.core.put(resourceID, lock); } return lock; } public synchronized void releaseLock(SysnKeyLock lock) { this.core.remove(lock.getKey()); this.cache.put(lock.getKey(), lock); } }
ResourceLock.java
public class ResourceLock { static SysnLockPool rtLockPool = new SysnLockPool(); public ResourceLock() { } public static SysnKeyLock accquireWrite(String resourceID) { SysnKeyLock lock = rtLockPool.getLock(resourceID); lock.lock(); return lock; } public static void releaseWrite(String resourceID) { SysnKeyLock lock = rtLockPool.getLock(resourceID); lock.unlock(); rtLockPool.releaseLock(lock); } }