1 Star 1 Fork 1

俊何 / distributedLocker

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

分布式锁

集群环境下保证ID不重复

原来的Synchronized + Lock只能锁单机,也就是只能在一个JVM环境下 单机

而在分布式+集群的环境下,变成了N对N的关系,在并发的环境下,如果使用UUID或者自增ID,就可能出现ID重复的问题,因此在集群下的环境下,对JVM进行加锁,这就是分布式锁。 分布式+集群

解决方案

  • mysql数据库的乐观锁实现(略)
  • redis:redission
  • zookeeper 总结一下他们各自的优劣
分布式锁 优点 缺点
Zookeeper 1.有封装好的框架,容易实现 2.有等待锁的队列,大大提升抢锁效率。 添加和删除节点性能较低
Redis Set和Del指令性能较高 1.实现复杂,需要考虑超时,原子性,误删等情形。2.没有等待锁的队列,只能在客户端自旋来等待,效率低下。

redisson 分布式锁

简介

  • 通过阅读redission锁的API可以得知,其获取锁释放锁的使用和JDK里面的lock很相似,底层的实现采用了类似lock的处理方式
  • redisson 依赖redis,因此使用redisson 锁需要服务端安装redis,而且redisson 支持单机和集群两种模式下的锁的实现
  • redisson 在多线程或者说是分布式环境下实现机制,其实是通过设置key的方式进行实现,也就是说多个线程为了抢占同一个锁

Redisson原理分析

代码实现
  1. pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>distributedLocker</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.11.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

    </dependencies>
</project>
  1. redisson锁需要依赖redis,application.yml 配置如下
spring:
  redis:
    database: 1
    host: localhost
    port: 6379
server:
  port: 8081
  1. 定义一个接口,redisson操作锁的API接口
public interface DistributedLocker {
    /**
     * 获取锁,并且加锁
     * 拿不到lock就不罢休,不然线程就一直block
     * @param lockKey 锁名
     * @return
     */
    RLock lock(String lockKey);

    /**
     * 获取锁,并且加锁
     * 拿不到lock就不罢休,不然线程就一直block
     * @param lockKey 锁名
     * @param timeout 超时时间-> 单位 SECONDS
     * @return
     */
    RLock lock(String lockKey, long timeout);

    /**
     * 获取锁,并且加锁
     *  拿不到lock就不罢休,不然线程就一直block
     * @param lockKey 锁名
     * @param unit  时间单位
     * @param timeout 超时时间
     * @return
     */
    RLock lock(String lockKey, TimeUnit unit, long timeout);

    /**
     * 在 waitTime 时间内 尝试获取锁,并加锁,超过waitTime 将结束等待 返回false
     * @param lockKey 锁名
     * @param unit 时间单位
     * @param waitTime 等待时间
     * @param leaseTime 锁过期时间,如果超过leaseTime还没有解锁的话, 我就强制解锁
     * @return
     */
    boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime);


    /**
     * 在 waitTime(默认5秒) 时间内 尝试获取锁,并加锁,超过waitTime(10秒) 将结束等待 返回false
     * @param lockKey
     * @return
     */
    boolean tryLock(String lockKey);

    /**
     * 解锁
     * @param lockKey
     */
    void unlock(String lockKey);

    /**
     * 解锁
     * @param lock
     */
    void unlock(RLock lock);
}
  1. 接口实现
@Component
public class RedissonDistributedLocker implements DistributedLocker{


    @Autowired
    private RedissonClient redissonClient;


    /**
     * 获取锁,并且加锁
     * 拿不到lock就不罢休,不然线程就一直block
     * @param lockKey 锁名
     * @return
     */
    @Override
    public RLock lock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        return lock;
    }

    /**
     * 获取锁,并且加锁
     * 拿不到lock就不罢休,不然线程就一直block
     * @param lockKey 锁名
     * @param timeout 超时时间-> 单位 SECONDS
     * @return
     */
    @Override
    public RLock lock(String lockKey, long timeout) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(timeout, TimeUnit.SECONDS);
        return lock;

    }

    /**
     * 获取锁,并且加锁
     *  拿不到lock就不罢休,不然线程就一直block
     * @param lockKey 锁名
     * @param unit  时间单位
     * @param timeout 超时时间
     * @return
     */
    @Override
    public RLock lock(String lockKey, TimeUnit unit, long timeout) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(timeout, unit);
        return lock;
    }


    /**
     * 在 waitTime 时间内 尝试获取锁,并加锁,超过waitTime 将结束等待 返回false
     * @param lockKey 锁名
     * @param unit 时间单位
     * @param waitTime 等待时间
     * @param leaseTime 锁过期时间,如果超过leaseTime还没有解锁的话, 我就强制解锁
     * @return
     */
    @Override
    public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 在 waitTime(默认5秒) 时间内 尝试获取锁,并加锁,超过waitTime(10秒) 将结束等待 返回false
     * @param lockKey
     * @return
     */
    @Override
    public boolean tryLock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(Constant.R_LOCK_DEFAULT_WAIT_TIME, Constant.R_LOCK_DEFAULT_LEASE_TIME, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            return false;
        }
    }

    /**
     * 解锁
     * @param lockKey
     */
    @Override
    public void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.unlock();
    }

    /**
     * 解锁
     * @param lock
     */
    @Override
    public void unlock(RLock lock) {
        lock.unlock();
    }
}
  1. 统一配置(可有可无)
public class Constant {

    public static final String R_LOCK = "r_lock_";

    /** redis分布式锁 默认等待时间 */
    public static final Long R_LOCK_DEFAULT_WAIT_TIME = 5L;

    /** redis分布式锁 默认超时时间 */
    public static final Long R_LOCK_DEFAULT_LEASE_TIME = 10L;
}
  1. redisson基本配置类,因为redisson支持多种模式下的配置,比如单机、集群、哨兵模式等,都可以根据实际业务需要进行配置,这里为演示方便使用单机配置(取redis中的配置,无需一下配置)
@Configuration
public class RedissonManager {

    @Value("${redisson.address}")
    private String addressUrl;

// 注意的是,在这个配置类里面,关于redis连接配置还有很多其他参数,比如像连接的用户名、密码、超时时间、连接的库信息等,可以根据需要往里面添加
    @Bean
    public RedissonClient getRedisson() throws Exception{
        RedissonClient redisson = null;
        Config config = new Config();
        config.useSingleServer()
                .setAddress(addressUrl);
        redisson = Redisson.create(config);

        System.out.println(redisson.getConfig().toJSON().toString());
        return redisson;
    }


}
  1. 写一个测试类,使用100个线程模拟一下获取锁的动作,第一次假如我们不释放锁,可以比较清楚看到哪个线程获取到了锁,接口请求一下,看看控制台打印结果

@RestController
@RequestMapping("/redisson")
public class RLockTestController {

    @Autowired
    private DistributedLocker distributedLocker;

    @RequestMapping("/test")
    public void redissonTest() {
        String key = Constant.R_LOCK + "test";
        for (int i = 0; i < 100; i++) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    boolean res = false;
                    try {
                        System.err.println("=============线程开启============" + Thread.currentThread().getName());
                        res = distributedLocker.tryLock(key); // 尝试获取锁,等待5秒,自己获得锁后一直不解锁则10秒后自动解锁
                        if (res) {
                            System.out.println("线程:" + Thread.currentThread().getName() + ",获取到了锁");
                            Thread.sleep(100); // 获得锁之后可以进行相应的处理
                            System.err.println("======获得锁后进行相应的操作======" + Thread.currentThread().getName());
                            System.err.println("=============================" + Thread.currentThread().getName());
                        } else {
                            System.err.println("获取锁失败");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (res) {
                            distributedLocker.unlock(key);
                        }
                    }
                }
            });
            t.start();
        }
    }
}

http://localhost:8081/redisson/test 控制台输出

=============线程开启============Thread-316
=============线程开启============Thread-317
=============线程开启============Thread-318
=============线程开启============Thread-319
=============线程开启============Thread-320
=============线程开启============Thread-321
=============线程开启============Thread-322
=============线程开启============Thread-323
=============线程开启============Thread-324
=============线程开启============Thread-325
=============线程开启============Thread-326
=============线程开启============Thread-327
=============线程开启============Thread-328
=============线程开启============Thread-329
=============线程开启============Thread-330
=============线程开启============Thread-331
=============线程开启============Thread-332
=============线程开启============Thread-333
=============线程开启============Thread-334
=============线程开启============Thread-335
=============线程开启============Thread-336
=============线程开启============Thread-337
=============线程开启============Thread-338
=============线程开启============Thread-339
=============线程开启============Thread-340
=============线程开启============Thread-341
=============线程开启============Thread-342
=============线程开启============Thread-343
=============线程开启============Thread-344
=============线程开启============Thread-345
=============线程开启============Thread-346
=============线程开启============Thread-347
=============线程开启============Thread-348
=============线程开启============Thread-349
=============线程开启============Thread-350
=============线程开启============Thread-351
=============线程开启============Thread-352
=============线程开启============Thread-353
=============线程开启============Thread-354
=============线程开启============Thread-355
=============线程开启============Thread-356
=============线程开启============Thread-357
=============线程开启============Thread-358
=============线程开启============Thread-359
=============线程开启============Thread-360
=============线程开启============Thread-361
=============线程开启============Thread-362
=============线程开启============Thread-363
=============线程开启============Thread-364
=============线程开启============Thread-365
=============线程开启============Thread-366
=============线程开启============Thread-367
=============线程开启============Thread-368
=============线程开启============Thread-369
=============线程开启============Thread-370
=============线程开启============Thread-371
=============线程开启============Thread-372
=============线程开启============Thread-373
=============线程开启============Thread-374
=============线程开启============Thread-375
=============线程开启============Thread-376
=============线程开启============Thread-377
=============线程开启============Thread-378
=============线程开启============Thread-379
=============线程开启============Thread-380
=============线程开启============Thread-381
=============线程开启============Thread-382
=============线程开启============Thread-383
=============线程开启============Thread-384
=============线程开启============Thread-385
=============线程开启============Thread-386
=============线程开启============Thread-387
=============线程开启============Thread-388
=============线程开启============Thread-389
=============线程开启============Thread-390
=============线程开启============Thread-391
=============线程开启============Thread-392
=============线程开启============Thread-393
=============线程开启============Thread-394
=============线程开启============Thread-395
=============线程开启============Thread-396
=============线程开启============Thread-397
=============线程开启============Thread-398
=============线程开启============Thread-399
=============线程开启============Thread-400
=============线程开启============Thread-401
=============线程开启============Thread-402
=============线程开启============Thread-403
=============线程开启============Thread-404
=============线程开启============Thread-405
=============线程开启============Thread-406
=============线程开启============Thread-407
=============线程开启============Thread-408
=============线程开启============Thread-409
=============线程开启============Thread-410
=============线程开启============Thread-411
=============线程开启============Thread-412
=============线程开启============Thread-413
=============线程开启============Thread-414
=============线程开启============Thread-415
线程:Thread-363,获取到了锁
======获得锁后进行相应的操作======Thread-363
=============================Thread-363
线程:Thread-380,获取到了锁
======获得锁后进行相应的操作======Thread-380
=============================Thread-380
线程:Thread-381,获取到了锁
======获得锁后进行相应的操作======Thread-381
=============================Thread-381
线程:Thread-324,获取到了锁
======获得锁后进行相应的操作======Thread-324
=============================Thread-324
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败
获取锁失败

zookeeper 分布式锁

安装zookeeper 请参考安装zookeeper

创建锁

多个JVM服务器之间,同时在zookeeper上创建相同一个临时节点,因为临时节点路径是保证唯一,只要谁能创建节点成功,谁就能获取到锁。

没有创建成功节点,只能注册个监听器监听这个锁并进行等待,当释放锁的时候,采用事件通知给其它客户端重新获取锁的资源。

这时候客户端使用事件监听,如果该临时节点被删除的话,重新进入获取锁的步骤。

释放锁

Zookeeper使用直接关闭临时节点session会话连接,因为临时节点生命周期与session会话绑定在一块,如果session会话连接关闭,该临时节点也会被删除,这时候客户端使用事件监听,如果该临时节点被删除的话,重新进入到获取锁的步骤。

代码实现

  1. pom.xml 添加配置
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.3.0</version>
        </dependency>
  1. zookeeper 连接端

Slf4j
@Data
public class ZKclient {


    private CuratorFramework client;

    //Zk集群地址
    private static final String ZK_ADDRESS = "localhost:2181";
    private static final String USER_NAME = "root";
    private static final String PASSWORD = "123456";
//    private static final String ZK_ADDRESS = "localhot:2181,localhot:2182,localhot:2183";

    public static ZKclient instance = null;

    static {
        instance = new ZKclient();
        instance.init();
    }

    private ZKclient() {

    }

    public void init() {

        if (null != client) {
            return;
        }
        //创建客户端
        if (USER_NAME != null && PASSWORD != null) {
            client = ClientFactory.create(ZK_ADDRESS, USER_NAME, PASSWORD);
        } else {
            client = ClientFactory.createSimple(ZK_ADDRESS);
        }
        //启动客户端实例,连接服务器
        client.start();
    }

    public void destroy() {
        CloseableUtils.closeQuietly(client);
    }
}
  1. zookeeper 连接实现
**
 * zookeeper 连接实现
 **/
public class ClientFactory {

    /**
     * @param connectionString zk的连接地址
     * @return CuratorFramework 实例
     */
    public static CuratorFramework createSimple(String connectionString) {
        // 重试策略:第一次重试等待1s,第二次重试等待2s,第三次重试等待4s
        // 第一个参数:等待时间的基础单位,单位为毫秒
        // 第二个参数:最大重试次数
        ExponentialBackoffRetry retryPolicy =
                new ExponentialBackoffRetry(1000, 3);

        // 获取 CuratorFramework 实例的最简单的方式
        // 第一个参数:zk的连接地址
        // 第二个参数:重试策略
        return CuratorFrameworkFactory.newClient(connectionString, retryPolicy);
    }

    /**
     *
     * @param zkAddress zk的连接地址
     * @param userName 账号
     * @param password 密码
     * @return
     */
    public static CuratorFramework create(String zkAddress, String userName, String password) {
        ExponentialBackoffRetry retryPolicy =
                new ExponentialBackoffRetry(1000, 3);
        return CuratorFrameworkFactory.builder()
                .authorization("digest", (userName + ":" + password).getBytes())
                .connectString(zkAddress)
                .retryPolicy(retryPolicy)
                .namespace("zk/lock").build();
    }

    /**
     * @param connectionString    zk的连接地址
     * @param retryPolicy         重试策略
     * @param connectionTimeoutMs 连接
     * @param sessionTimeoutMs
     * @return CuratorFramework 实例
     */
    public static CuratorFramework createWithOptions(
            String connectionString, RetryPolicy retryPolicy,
            int connectionTimeoutMs, int sessionTimeoutMs) {

        // builder 模式创建 CuratorFramework 实例
        return CuratorFrameworkFactory.builder()
                .connectString(connectionString)
                .retryPolicy(retryPolicy)
                .connectionTimeoutMs(connectionTimeoutMs)
                .sessionTimeoutMs(sessionTimeoutMs)
                // 其他的创建选项
                .build();
    }


}
  1. 分布式锁接口
public interface DistributedZLock {
    /**
     * 加锁
     * 拿不到lock就不罢休,不然线程就一直block
     * @param lock 锁
     * @return
     */
    void lock(InterProcessLock lock);


    /**
     * 获取锁
     * @param lockKey 锁名
     * @return
     */
    InterProcessLock getLock(String lockKey);


    /**
     * 在 waitTime 时间内 加锁,超过waitTime 将结束等待 返回false
     * @param lock 锁
     * @param unit 时间单位
     * @param waitTime 等待时间
     * @return
     */
    boolean tryLock(InterProcessLock lock, TimeUnit unit, long waitTime);


    /**
     * 在 waitTime(默认5秒) 时间内 尝试加锁,超过waitTime(10秒) 将结束等待 返回false
     * @param lock
     * @return
     */
    boolean tryLock(InterProcessLock lock);

    /**
     * 解锁
     * @param lock
     */
    void unlock(InterProcessLock lock);


}
  1. 分布式锁实现类
@Component
public class ZookeeperDistributedLock implements DistributedZLock {
    @Override
    public void lock(InterProcessLock lock) {
        try {
             lock.acquire();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public InterProcessLock getLock(String lockKey) {
        return new InterProcessSemaphoreMutex(ZKclient.instance.getClient(), lockKey);
    }


    @Override
    public boolean tryLock(InterProcessLock lock, TimeUnit unit, long waitTime) {
        try {
            return lock.acquire(waitTime, unit);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean tryLock(InterProcessLock lock) {
        try {
            lock.acquire(Constant.R_LOCK_DEFAULT_WAIT_TIME, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void unlock(InterProcessLock lock) {
        try {
            lock.release();
        } catch (Exception e) {
//            e.printStackTrace();
            System.out.println("解锁失败");
        }
    }

}
  1. 测试
 @Test
    public void testLock2() throws Exception {
        String lockKey = Constant.Z_LOCK + "test";
        for (int i = 0; i < 30; i++) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    boolean res = false;
                    InterProcessLock lock = distributedZLock.getLock(lockKey);
                    try {
                        System.err.println("=============线程开启============" + Thread.currentThread().getName());
                        res = distributedZLock.tryLock(lock); // 尝试获取锁,等待5秒,自己获得锁后一直不解锁则10秒后自动解锁
                        if (res) {
                            System.out.println("线程:" + Thread.currentThread().getName() + ",获取到了锁");
                            Thread.sleep(50); // 获得锁之后可以进行相应的处理
                            System.err.println("======获得锁后进行相应的操作======" + Thread.currentThread().getName());
                            System.err.println("=============================" + Thread.currentThread().getName());
                        } else {
                            System.err.println("获取锁失败");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (res) {
                            distributedZLock.unlock(lock);
                        }
                    }
                }
            });
            t.start();
        }
        Thread.sleep(10000);
    }
  1. 结果
=============线程开启============Thread-8
=============线程开启============Thread-3
=============线程开启============Thread-13
=============线程开启============Thread-30
=============线程开启============Thread-5
=============线程开启============Thread-29
=============线程开启============Thread-14
=============线程开启============Thread-16
=============线程开启============Thread-17
=============线程开启============Thread-24
=============线程开启============Thread-20
=============线程开启============Thread-12
=============线程开启============Thread-11
=============线程开启============Thread-28
=============线程开启============Thread-21
=============线程开启============Thread-9
=============线程开启============Thread-22
=============线程开启============Thread-10
=============线程开启============Thread-4
=============线程开启============Thread-15
=============线程开启============Thread-31
=============线程开启============Thread-6
=============线程开启============Thread-23
=============线程开启============Thread-32
=============线程开启============Thread-19
=============线程开启============Thread-18
=============线程开启============Thread-26
=============线程开启============Thread-27
=============线程开启============Thread-25
=============线程开启============Thread-7
线程:Thread-13,获取到了锁
======获得锁后进行相应的操作======Thread-13
=============================Thread-13
线程:Thread-20,获取到了锁
======获得锁后进行相应的操作======Thread-20
=============================Thread-20
线程:Thread-9,获取到了锁
======获得锁后进行相应的操作======Thread-9
=============================Thread-9
线程:Thread-10,获取到了锁
======获得锁后进行相应的操作======Thread-10
=============================Thread-10
线程:Thread-28,获取到了锁
======获得锁后进行相应的操作======Thread-28
=============================Thread-28
线程:Thread-32,获取到了锁
======获得锁后进行相应的操作======Thread-32
=============================Thread-32
线程:Thread-14,获取到了锁
======获得锁后进行相应的操作======Thread-14
=============================Thread-14
线程:Thread-29,获取到了锁
======获得锁后进行相应的操作======Thread-29
=============================Thread-29
线程:Thread-24,获取到了锁
======获得锁后进行相应的操作======Thread-24
=============================Thread-24
线程:Thread-15,获取到了锁
======获得锁后进行相应的操作======Thread-15
=============================Thread-15
线程:Thread-22,获取到了锁
======获得锁后进行相应的操作======Thread-22
=============================Thread-22
线程:Thread-18,获取到了锁
======获得锁后进行相应的操作======Thread-18
=============================Thread-18
线程:Thread-19,获取到了锁
======获得锁后进行相应的操作======Thread-19
=============================Thread-19
线程:Thread-11,获取到了锁
======获得锁后进行相应的操作======Thread-11
=============================Thread-11
线程:Thread-21,获取到了锁
======获得锁后进行相应的操作======Thread-21
=============================Thread-21
线程:Thread-23,获取到了锁
======获得锁后进行相应的操作======Thread-23
=============================Thread-23
线程:Thread-3,获取到了锁
======获得锁后进行相应的操作======Thread-3
=============================Thread-3
线程:Thread-4,获取到了锁
======获得锁后进行相应的操作======Thread-4
=============================Thread-4
线程:Thread-30,获取到了锁
======获得锁后进行相应的操作======Thread-30
=============================Thread-30
线程:Thread-8,获取到了锁
======获得锁后进行相应的操作======Thread-8
=============================Thread-8
线程:Thread-7,获取到了锁
======获得锁后进行相应的操作======Thread-7
=============================Thread-7
线程:Thread-31,获取到了锁
======获得锁后进行相应的操作======Thread-31
=============================Thread-31
线程:Thread-16,获取到了锁
======获得锁后进行相应的操作======Thread-16
=============================Thread-16
线程:Thread-5,获取到了锁
======获得锁后进行相应的操作======Thread-5
=============================Thread-5
线程:Thread-25,获取到了锁
======获得锁后进行相应的操作======Thread-25
=============================Thread-25
线程:Thread-12,获取到了锁
线程:Thread-27,获取到了锁
线程:Thread-6,获取到了锁
线程:Thread-17,获取到了锁
线程:Thread-26,获取到了锁
======获得锁后进行相应的操作======Thread-27
=============================Thread-27
======获得锁后进行相应的操作======Thread-26
=============================Thread-26
解锁失败
解锁失败
======获得锁后进行相应的操作======Thread-12
解锁失败
=============================Thread-12
======获得锁后进行相应的操作======Thread-17
=============================Thread-17
解锁失败
======获得锁后进行相应的操作======Thread-6
=============================Thread-6

源码

空文件

简介

java 分布式锁 展开 收起
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/aihl/distributedLocker.git
git@gitee.com:aihl/distributedLocker.git
aihl
distributedLocker
distributedLocker
master

搜索帮助