java+Redisson实现分布式锁

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u013451024/article/details/52757048

           我在此谈谈自己对java锁(java.util.concurrent.locks)的理解以及分布式的环境下锁的处理。在大型项目高访问量高并发量是在所难免的,为了解决此类问题,我们需要用到锁。

          首先,在单机的环境下线程竞争同一资源,需要获取一个同步锁,谁先得到谁就可以进入第二关获取分布式锁。通过Redisson的机制我们可以在不同机器的情况下同时竞争同一个key的锁,哪一台机器得到此锁就有处理的优先权。其他服务器就只能等待获取分布式锁(当然等待也会有超时,超时默认当作响应失败),处理完成后释放锁,其他线程就可以继续竞争该锁。

         在实现的过程中要注意的地方对锁释放的处理,一般如果使用了锁在超时或程序报异常等情况下就需要释放下锁unlock();

   最后附上一些核心关键性代码。

public class Lock implements ILock {

    private static final int PERIOD = 100;

    private static final HashMap<String, RlockThread> rLockTheads = new HashMap<>();
    private static final HashMap<String, ReentrantLock> sMap = new HashMap<>();
    private static final HashMap<String, Integer> sMapNum = new HashMap<>();
    private static final HashMap<String, Object> sKey = new HashMap<>();
    private RedissonClient redissonClient;
    private String key;

    private Lock(String key, RedissonHelper redissonHelper) { //初始化锁
        this.key = key;
        redissonClient = redissonHelper.getClient();

    }

    @Override
    public boolean require(long waitTime, long leaseTime, TimeUnit timeUnit) {

        num(1);//计数器
        boolean r1 = false;
        try {
            ReentrantLock reentrantLock = sMap.get(key);
            r1 = reentrantLock.tryLock(waitTime, timeUnit);
        } catch (Exception e) {
            e.printStackTrace();
            num(-1);

            return false;
        }
        if (!r1) {
            num(-1);
            return false;
        }

        RlockThread rlockThread = rLockTheads.get(key);
        if (rlockThread == null) {
            CountDownLatch countDownLatch = new CountDownLatch(1);
            rlockThread = new RlockThread(waitTime, leaseTime, timeUnit, countDownLatch);
            try {
                rlockThread.start();
                countDownLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
                unlockReentrantLock();
                return false;
            }
            if (!rlockThread.isGotLock) {
                unlockReentrantLock();
                return false;
            }
            rLockTheads.put(key, rlockThread);
        }
        return true;
    }


    private int num(int incr) {
        Object kk = sKey.get(key);
        if (kk == null) {
            synchronized (sKey) {
                kk = sKey.get(key);
                if (kk == null) {
                    kk = new Object();
                    sKey.put(key, kk);
                }
            }
        }
        synchronized (kk) {
            int _num;
            Integer num = sMapNum.get(key);
            if (num == null) {
                _num = 0;
            } else {
                _num = num;
            }
            _num += incr;
            if (_num > 0) {
                sMapNum.put(key, _num);
                ReentrantLock lock = sMap.get(key);
                if (lock == null) {
                    lock = new ReentrantLock();
                    sMap.put(key, lock);
                }
            } else {
                ReentrantLock locks = sMap.remove(key);
                System.out.println("r:"+locks);
                sMapNum.remove(key);
                sKey.remove(key);
                if (locks != null) {
                }
                RlockThread rlockThread = rLockTheads.remove(key);
                if (rlockThread != null) {
                    rlockThread.unLock();
                }

            }
            return _num;
        }
    }

    private void unlockReentrantLock() {
        ReentrantLock reentrantLock = sMap.get(key);
        num(-1);
        reentrantLock.unlock();
    }

    @Override
    public void release() {
        unlockReentrantLock();
    }

    public class RlockThread extends Thread {
        private long waitTime;
        private long leaseTime;
        private TimeUnit timeUnit;
        private CountDownLatch countDownLatch;

        private CountDownLatch callback;
        private boolean isGotLock = false;

        public RlockThread(long waitTime, long leaseTime, TimeUnit timeUnit, CountDownLatch countDownLatch) {
            this.waitTime = waitTime;
            this.leaseTime = leaseTime;
            this.timeUnit = timeUnit;
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            super.run();
            RLock rLock = null;
            boolean r = false;
            try {
                rLock = redissonClient.getLock(key);
                long start = System.currentTimeMillis();
                while (true) {
                    Thread.sleep(PERIOD);
                    r = rLock.tryLock();
                    if (r) {
                        break;
                    }
                    long wai = timeUnit.toMillis(waitTime);
                    if (System.currentTimeMillis() - start > wai) {             
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                countDownLatch.countDown();
                return;
            }
            if (!r) {
                countDownLatch.countDown();
                return;
            }
            isGotLock = true;
            callback = new CountDownLatch(1);
            countDownLatch.countDown();
            try {
                callback.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
                rLockTheads.remove(key);
            }
            if (rLock != null) {
                rLock.unlock();
            }

        }

        public void unLock() {
            callback.countDown();
        }
    }

    @Component
    public static class LockBuilder {

        @Autowired
        private RedissonHelper redissonHelper;

        public ILock build(String key) {
            return new Lock(key, redissonHelper);
        }
    }
}

展开阅读全文

没有更多推荐了,返回首页