同步锁实现
一、背景
在并发场景下,需要单一线程或限定并发数操作某些逻辑,这时候就需要用到一个锁来保证线程安全。
二、思路
- 使用ConcurrentHashMap实现,但只支持同一个jvm下的线程(暂时满足)
- 使用Semaphore信号量作为锁
- 数量操作都使用java原子操作类,例:AtomicInteger、AtomicLong等
三、实操
-
构建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(); } }
-
编写同步锁工具类
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