/**
* 实体资源锁,防止多个线程操作同一个资源的锁,根据实体ID生成唯一锁,前提是实体ID的字符串唯一性 只适用于资源同时操作数量不多的系统
*
* @author xuzhaojie
*
* ---2016-12-1 上午10:35:30
*/
public class ResourceLock {
private static final Logger log = Logger.getLogger(CommonParams.LOG_SYS);
// 初始化ConcurrentHashMap锁载体
private static final ConcurrentHashMap<String, AtomicInteger> lockMap = new ConcurrentHashMap<String, AtomicInteger>();
public static AtomicInteger getAtomicInteger(String key) {
if (lockMap.get(key) == null) {// 当实体ID锁资源为空,初始化锁
lockMap.putIfAbsent(key, new AtomicInteger(0));// 初始化一个竞争数为0的原子资源
}
int count = lockMap.get(key).incrementAndGet();// 线程得到该资源,原子性+1
log.debug("资源ID为:" + key + ",争抢线程数:" + count);
return lockMap.get(key);// 返回该ID资源锁
}
public static void giveUpAtomicInteger(String key) {
if (lockMap.get(key) != null) {// 当实体ID资源不为空,才可以操作锁,防止抛出空指针异常
int source = lockMap.get(key).decrementAndGet();// 线程释放该资源,原子性-1
if (source <= 0) {// 当资源没有线程竞争的时候,就删除掉该锁,防止内存溢出
lockMap.remove(key);
log.debug("资源ID为:" + key + "移除成功");
}
log.debug("资源ID为:" + key + ",争抢线程数:" + source);
}
}
}
很多时候,在我们业务系统中都会有多个线程操作同一个ID资源的数据,如果将修改数据的方法锁上同类型数据的大锁就会降低系统性能。所以为了要更高的并发性能,我们需要粒度更细的锁去控制,所以就有以上的代码,不太会说,见谅
AtomicInteger resource = ResourceLock.getAtomicInteger(ID);
synchronized (resource) {// 防止多个线程同时操作数据同一条实体数据
//业务操作
}
ResourceLock.giveUpAtomicInteger(ID);