首页 > 其他分享 > 单一JVM同步锁实现

单一JVM同步锁实现

时间:2022-12-06 15:01:27浏览次数:43  
标签:同步 return acquireNum 单一 ThreadData 线程 JVM lockKey public

同步锁实现

一、背景

在并发场景下,需要单一线程或限定并发数操作某些逻辑,这时候就需要用到一个锁来保证线程安全。

二、思路

  • 使用ConcurrentHashMap实现,但只支持同一个jvm下的线程(暂时满足)
  • 使用Semaphore信号量作为锁
  • 数量操作都使用java原子操作类,例:AtomicInteger、AtomicLong等

三、实操

  1. 构建Key锁对象

    import java.util.concurrent.Semaphore;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * key锁对象
     */
    public class ThreadData {
        private String lockKey;
        private Semaphore lock;
        //线程id
        private long threadId;
        //当前线程获取的锁数量
        private AtomicInteger acquireNum;
    
        // 第一次加锁时间
        private Long startTime;
    
        public ThreadData(String lockKey, long threadId, AtomicInteger acquireNum) {
            this.lockKey = lockKey;
            this.threadId = threadId;
            this.acquireNum = acquireNum;
            this.lock = new Semaphore(acquireNum.get());
            this.startTime = System.currentTimeMillis();
        }
    
        public static ThreadData newInstance(String lockKey, int maxNum) {
            return new ThreadData(lockKey, Thread.currentThread().getId(), new AtomicInteger(maxNum));
        }
    
        /**
         * 增加当前线程占用锁的数量
         *
         * @return
         */
        public int incrementAcquireNum() {
            return this.acquireNum.incrementAndGet();
        }
    
        /**
         * 减少当前线程锁的占有数量
         *
         * @return
         */
        public int decrementAcquireNum() {
            return this.acquireNum.decrementAndGet();
        }
    
        public long getThreadId() {
            return threadId;
        }
    
        public void setThreadId(long threadId) {
            this.threadId = threadId;
        }
    
        public Integer getAcquireNum() {
            return acquireNum.get();
        }
    
        public void setAcquireNum(Integer acquireNum) {
            this.acquireNum.set(acquireNum);
        }
    
        private Semaphore getLock() {
            return lock;
        }
    
        public Long getStartTime() {
            return startTime;
        }
    
        /**
         * 获取锁
         */
        public void lock() throws InterruptedException {
            getLock().acquire();
        }
    
        /**
         * 在指定时间内获取锁
         *
         * @param waitTimeout
         * @param timeUnit
         */
        public Boolean tryLock(int waitTimeout, TimeUnit timeUnit) throws InterruptedException {
            return getLock().tryAcquire(waitTimeout, timeUnit);
        }
    
        /**
         * 只有被当前线程持有锁的情况下才能释放锁
         */
        public void release() {
            lock.release();
        }
    }
    
  2. 编写同步锁工具类

    import com.jravity.jrlive.utils.StringHelper;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 同步锁,ConcurrentHashMap 实现,只支持同一个jvm下的线程
     */
    @Slf4j
    public class KeyLock {
    
        private final static ConcurrentHashMap<String, ThreadData> HAPPY_LOCK_MAP = new ConcurrentHashMap<String, ThreadData>();
        private final String lockKey;
        //最大并发数
        private int maxNum;
    
        public KeyLock(String lockKey) {
            if (StringHelper.isBlank(lockKey)) {
                throw new NullPointerException("lock key can not be null");
            }
            this.lockKey = lockKey;
            maxNum = 1;
        }
    
        public KeyLock(String lockKey, int maxNum) {
            if (StringHelper.isBlank(lockKey)) {
                throw new NullPointerException("lock key can not be null");
            }
            this.lockKey = lockKey;
            this.maxNum = maxNum;
        }
    
    
        /**
         * 获取

    标签:同步,return,acquireNum,单一,ThreadData,线程,JVM,lockKey,public
    From: https://www.cnblogs.com/checkcode/p/lock_1.html

相关文章