Java教程

java实现key粒度的锁

本文主要是介绍java实现key粒度的锁,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

在使用redis缓存时,为了避免因为缓存不存在的key,导致大量请求打到mysql时,需要对代码块加锁,只让一个线程进入mapper层,查询数据,然后放在缓存中即可package com.xtoshii.xcs.util;

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @program: xcs-boot2
 * @description:
 * @author: xtoshii
 * @create: 2021-08-11 22:44
 **/
@Slf4j
@NoArgsConstructor
public class KeyLocker<T> {

    private  Map<T,Lock> lockMap = new ConcurrentHashMap<>();

    public KeyLocker(int capacity){
        this.lockMap = new ConcurrentHashMap<>(capacity);
    }

    public boolean tryLock(T t){
        if(Objects.isNull(t)){
            throw new NullPointerException();
        }
        if(lockMap.containsKey(t)){
            ReentrantLock lock = (ReentrantLock)lockMap.get(t);
            return lock.isHeldByCurrentThread();//  判断是否当前线程已持有锁,若持有,则返回true,否则为false
        } else {
            Lock lock = new ReentrantLock();
            if(lock.tryLock()){
                lockMap.put(t,lock);
                log.info("{} 获得资源 {}",Thread.currentThread().getName(),t);
                return true;
            }
            return false;
        }
    }

    public boolean tryRelease(T t){
        if(Objects.nonNull(t) && lockMap.containsKey(t) ){
            ReentrantLock lock = (ReentrantLock)lockMap.get(t);// 先判断是否锁是否有当前线程持有,持有方可解锁,否则会抛出 java.lang.IllegalMonitorStateException
            if(lock.isHeldByCurrentThread()){
                lock.unlock();
                lockMap.remove(t);
                log.info("{} 释放了锁 {}", Thread.currentThread().getName(), t);
                return true;
            }
        }
        return  false;
    }
}

  

这篇关于java实现key粒度的锁的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!