锁的double-check机制

先举例一个场景。一个货架有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。可以保证每个仓位有且仅有一个自己独立的锁。

上一篇:MySQL 性能优化-数据库死锁监控


下一篇:Java性能监控及调优工具