分布式锁(一):使用redis乐观锁实现CAS

环境 四台tomcat作为集群,redis作为共享内存。
需求 对于一个共享状态的改变进行加锁,锁的属性为互斥且可重入
实现 仿照ReentrantLock类写一个分布式锁
问题 CAS实现
解决 使用redis乐观锁实现CAS

CAS(compare and swap)

比较并交换;在替换新值前比较一下旧值是否为传入的值,如果一样则替换,当然这样会产生ABA问题,即当原值为A,随后变成了B接着又变成了A,那么进行比较时发现值没有改变,其实已经改变了,解决方法则是为值添加上版本号。

使用redis事务实现乐观锁请查看《利用redis乐观锁实现tomcat集群抢占定时任务》,该文前小半部分是乐观锁的实现。

代码实现

利用redis创建一个hash,里面有三个值,state(状态)值为0,1,2,…;exclusiveownerthreadname(占有线程名)值为唯一的名称,可以IP+线程名或者IP+UUID+线程名;nouse(无用)值任意,为实现判断乐观锁设置的字段,无实际用处,下文有解释。本段代码只使用了state和nouse两个字段。

	/**
     * 比较并设置值 利用乐观锁实现CAS
     * @param jedis redis连接
     * @param key 锁的key
     * @param oldState 比较值
     * @param newState 替换值
     * @return
     */
    private boolean compareAndSetState(Jedis jedis, String key, int oldState, int newState) {
        boolean retBoolean;
        while (true) {
            retBoolean = false;
            try {
                jedis.watch(key);
                Transaction tran;
                List result = null;
                if (jedis.exists(key)) {
                    int state = Integer.parseInt(jedis.hget(key, ConcurrentGlobal.PUBLIC_DISTRIBUTEDREENTRANTLOCK_STATE));
                    tran = jedis.multi();
                    if (state == oldState) {
                        retBoolean = true;
                        tran.hset(key, ConcurrentGlobal.PUBLIC_DISTRIBUTEDREENTRANTLOCK_STATE, String.valueOf(newState));
                    } else {
                        // 随便保存一个key保持事务中有一个任务
                        tran.hset(key, ConcurrentGlobal.PUBLIC_DISTRIBUTEDREENTRANTLOCK_NOUSE, "1");
                    }
                } else {
                    tran = jedis.multi();
                    retBoolean = true;
                    tran.hset(key, ConcurrentGlobal.PUBLIC_DISTRIBUTEDREENTRANTLOCK_STATE, String.valueOf(newState));
                }
                result = tran.exec();
                if (result != null && !result.isEmpty()) {
                    break;
                }
            } finally {
                jedis.unwatch();
            }
        }
        return retBoolean;
    }

该段代码并没有解决ABA问题。

代码解析

分布式锁(一):使用redis乐观锁实现CAS_第1张图片
个人理解其实乐观锁和CAS很相似,都是原子性实现某些操作。

你可能感兴趣的:(java,tomcat集群)