使用synchronized能够处理并发
例子:
@Service
public class SecKillServiceImpl implements SecKillService {
private static final int TIMEOUT = 10 * 1000; //超时时间 10s
@Autowired
private RedisLock redisLock;
/**
* 国庆活动,皮蛋粥特价,限量100000份
*/
static Map<String,Integer> products;
static Map<String,Integer> stock;
static Map<String,String> orders;
static
{
/**
* 模拟多个表,商品信息表,库存表,秒杀成功订单表
*/
products = new HashMap<>();
stock = new HashMap<>();
orders = new HashMap<>();
products.put("123456", 100000);
stock.put("123456", 100000);
}
private String queryMap(String productId)
{
return "国庆活动,皮蛋粥特价,限量份"
+ products.get(productId)
+" 还剩:" + stock.get(productId)+" 份"
+" 该商品成功下单用户数目:"
+ orders.size() +" 人" ;
}
@Override
public String querySecKillProductInfo(String productId)
{
return this.queryMap(productId);
}
@Override
public void orderProductMockDiffUser(String productId)
{
//加锁
//1.查询该商品库存,为0则活动结束。
int stockNum = stock.get(productId);
if(stockNum == 0) {
throw new SellException(100,"活动结束");
}else {
//2.下单(模拟不同用户openid不同)
orders.put(KeyUtil.genUniqueKey(),productId);
//3.减库存
stockNum =stockNum-1;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
stock.put(productId,stockNum);
}
//解锁
}
}
如上图所示: 方法orderProductMockDiffUser没有添加同步锁
结果如下:
这里需要压测工具,如不清楚可看以下文章 https://blog.csdn.net/qq_38882630/article/details/102957436
输入命令:
ab -n 500 -c 100 http://localhost:8080/sell/skill/order
--意思是 500次请求 100并发 (100人同时访问)
可以很清楚的发现 库存数和下单人数不一致
加上synchronized过后 再去测试一遍会发现
测试过程中访问速度变得很慢了。但是结果是正确的。
过了近40秒后 无论怎么去测试 库存数和下单人数始终是一致的
总结如下: 它是一种解决方法, 这是不可否认的,可是它只适合单点的情况,无法做到细粒度控制。这就需要redis分布式锁了。