synchronized

synchronized原理

ReentrantLock

ReentrantReadWriteLock

StampedLock

锁调优

分布式锁

借助第三方公共组件

基于数据库实现

基于redis的setnx实现

set resource_name my_random_value NX PX 30000
resource_name:资源名称,可根据不同的业务区分不同的锁
my_random_value:随机值,每个线程的随机值都不同,用于释放锁时的校验
NX:key不存在时设置成功,key存在则设置不成功
PX:自动失效时间,出现异常情况,锁可以过期失效

基于redisson实现

基于zookeeper的瞬时节点实现

@Slf4j
public class ZkLock implements AutoCloseable, Watcher {

    private ZooKeeper zooKeeper;

    private String znode;

    public ZkLock() throws IOException {
        this.zooKeeper = new ZooKeeper("127.0.0.1:2181", 10000, this);
    }

    public boolean getLock(String businessCode) {
        try {
            // 创建业务根节点
            Stat stat = zooKeeper.exists("/" + businessCode, false);
            if (stat == null) {
                zooKeeper.create("/" + businessCode, businessCode.getBytes(),
                        ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
            // 创建瞬时有序节点
            znode = zooKeeper.create("/" + businessCode + "/" + businessCode + "_",
                    businessCode.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
            // 获取业务节点下所有节点
            List<String> childrenList = zooKeeper.getChildren("/" + businessCode, false);
            // 子节点排序
            Collections.sort(childrenList);
            String firstNode = childrenList.get(0);
            // 如果创建的节点是第一个节点,则获得锁
            if (znode.endsWith(firstNode)) {
                return true;
            }
            // 如果不是第一个子节点,则监听前一个节点
            String lastNode = firstNode;
            for (String node : childrenList) {
                if (znode.endsWith(node)) {
                    zooKeeper.exists("/" + businessCode + "/" + lastNode, true);
                }else {
                    lastNode = node;
                }
            }
            synchronized (this) {
                wait();
            }
            return true;
        } catch (Exception e) {
            log.error("获取锁失败:", e);
        }
        return false;
    }

    @Override
    public void close() throws Exception {
        zooKeeper.delete(znode, -1);
        zooKeeper.close();
    }

    @Override
    public void process(WatchedEvent watchedEvent) {
        if (watchedEvent.getType() == Event.EventType.NodeDeleted) {
            synchronized (this) {
                notify();
            }
        }
    }
}

基于zookeeper的curator客户端实现

// 连接
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);
curatorFramework.start();
//
InterProcessMutex lock = new InterProcessMutex(curatorFramework, "/order");
try {
    if (lock.acquire(30, TimeUnit.SECONDS)) {
        try {
            log.info("获得锁");
        }finally {
            lock.release();
        }
    }
} catch (Exception e) {
    log.error("获得锁失败");
}
curatorFramework.close();

对比

发表评论

发表
Table of Contents