说明,在工作中遇到的一个类似于单例模式双重加锁与redis结合的应用,因此记录下来,但是最开始代码有些问题,之后我做了些改进
1、synchronized加锁
- 场景,根据商品id(itemId)去查找商品,先从缓存中获取,缓存中获取不到再从数据库中获取。最开始的伪代码如下,但存在一些问题:
String key = String.format("item.detail.%s", itemId);
// 从redis中获取数据-这里可能有多个线程同时从redis中获取数据
ItemDetailVO vo = redisTemplate.opsForValue().get(key);
// 如果redis里面为空,那么需要从数据库中获取数据。不为空直接返回
if (null == vo) {
// 加锁,只允许一个线程去访问数据库,避免线程过多造成mysql压力过大
synchronized (this) {
// 这里再从redis中获取一下值,因为可能其它线程已经从数据库里面获取了值
vo = redisTemplate.opsForValue().get(key);
// 如果为空,则通过getItemDetail方法从数据库中获取值
if (null == vo) {
vo = getItemDetail(itemId);
if (null != vo) {