上锁原则:能不加锁尽量不加锁。能锁局部,不锁全部。
一、redisson分布式锁
1、导入依赖
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.23.1</version> </dependency>
2、添加配置类
@Configuration public class RedissonConfig { @Bean public RedissonClient initRedisson(){ Config config = new Config(); config.useSingleServer().setAddress("redis://localhost:6379").setPassword("密 码"); return Redisson.create(config); } }
3、java代码
//获取锁对象实例(无法保证是按线程的顺序获取到) RLock lock = redissonClient.getLock("lock:" + item.getItemId()); //尝试获取锁 //尝试获取锁的最大等待时间,超过这个值,则认为获取锁失败 // 锁的持有时间,超过这个时间锁会自动失效(值应设置为大于业务处理的时间,确保在锁有效期内业务能处理完) boolean flag = lock.tryLock(30, 30, TimeUnit.SECONDS); if(flag){ try{ //成功获得锁,在这里处理业务 }catch(Exception e){ e.printStackTrace();; }finally { //无论如何, 最后都要解锁 lock.unlock(); } }
二、 synchronized同步锁(同一时刻,只能有一个线程访问)
synchronized (this){
//成功获得锁,在这里处理业务
}
三、不上锁
/* 先扣库存,在判断库存数。如果不足则补上,充足则继续业务 */ //扣减可售库存,增加锁定库存 Long newSaleNum = stringRedisTemplate.opsForHash().increment("goods:" + item.getItemId(), "saleNum", item.getNum() * -1); if(newSaleNum<0){ //本次超售 stringRedisTemplate.opsForHash().increment("goods:"+item.getItemId(),"saleNum", item.getNum()); items.remove(item); continue; } //本次不会超售 Map<Object, Object> cache = stringRedisTemplate.opsForHash().entries("goods:" + item.getItemId()); stringRedisTemplate.opsForHash().increment("goods:"+item.getItemId(),"lockNum", item.getNum());