先举例一个场景。一个货架有10个仓位。每个仓位可以补货,也可以拣货,补货是加库存,拣货是减库存,补货和拣货可以同时发生,比如两个人同时按PDA操作。每个仓位的补货和拣货操作独立。
针对货架上每个仓位的补货和拣货,此时务必要关注并发问题,此时有一种思路,悲观锁,用java锁做。当然其他方法也很多,此时不谈。
java的悲观锁应该说是单机部署时解决这种问题比较简单的方案。springboot程序。
首先定义锁的提供者ILockProvider.class接口:
package com.impl;
public interface ILockProvider<T> {
T getLock(String key);
}
ObjLockProvider.class实现。这里面用了double-check机制。类似单例的生成,保证10个仓位,每个仓位有且仅有一个object对象作为锁持有者。
package com.service;
import com.impl.ILockProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Slf4j
public class ObjLockProvider implements ILockProvider<Object> {
private final Map<String,Object> locks=new ConcurrentHashMap();
//double check机制。synchronized关键字用
@Override
public Object getLock(String key) {
Object object=locks.get(key);
if(null==object)
{
synchronized (this)
{
if(null==locks.get(key))
{
log.info("首次申请锁"+key);
locks.put(key,new Object());
}
}
}
return locks.get(key);
}
}
跑一下如下代码:
for(int i=0;i<1000;i++)
{
new Thread(
new Runnable() {
@Override
public void run() {
//用param模拟仓位号。仓位号从0到9
String param=new Random().nextInt(10)+"";
final Object object=objLockProvider.getLock(param);
synchronized(object)
{
//log.info("开始查询库存"+param);
//log.info("库存操作完毕"+param);
}
}
}
).start();
}
控制台上打印的log.info("首次申请锁"+key)。只有10次,分别为0到9。可以保证每个仓位有且仅有一个自己独立的锁。