专栏首页悠扬前奏的博客ZK实现的分布式锁

ZK实现的分布式锁

原理

zk能保证集群上的路径同一时刻只有一个客户端来创建。因此,通过在集群上顺序创建和删除临时路径,在实现分布式锁的获取和释放。

代码

zk上有一个客户端框架Curator已经对分布式互斥锁进行了封装,几乎是开箱即用:

  • 封装一下框架的初始化
public class ZKCuratorManager {
    private static InterProcessMutex lock;
    private static CuratorFramework cf;
    private static String zkAddr = "*.*.*.*:2181";
    private static String lockPath = "/distribute-lock";

    static {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        cf = CuratorFrameworkFactory.builder()
                .connectString(zkAddr)
                .sessionTimeoutMs(2000)
                .retryPolicy(retryPolicy)
                .build();
        cf.start();
    }

    public static InterProcessMutex getLock() {
        lock = new InterProcessMutex(cf, lockPath);
        return lock;
    }
}
  • 封装一下工具类
public class ZKCuratorLockUtil {

    /**
     * 从配置类中获取分布式锁对象
     */
    private static InterProcessMutex lock = ZKCuratorManager.getLock();

    /**
     * 加锁
     *
     * @return
     */
    public static boolean acquire() {
        try {
            lock.acquire();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 锁的释放
     */
    public static void release() {
        try {
            lock.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 测试
    • 所有线程启动后sleep5秒钟
    • 用CyclicBarrier使四个线程同时尝试获取锁
    • 结果应该是四个线程依次获取-释放锁
public class ZkLockTest {

    public static void main(String[] args) {
        int N = 4;
        CyclicBarrier barrier = new CyclicBarrier(N);
        for (int i = 0; i < N; i++) {

            new WriterTest(barrier).start();
        }

        System.out.println("END");
    }

    static class WriterTest extends Thread {
        private CyclicBarrier cyclicBarrier;

        public WriterTest(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            System.out.println("线程" + Thread.currentThread().getName() + "正在写入数据...");
            try {
                //以睡眠来模拟写入数据操作
                Thread.sleep(5000);
                System.out.println("线程" + Thread.currentThread().getName() + "写入数据完毕,等待其他线程写入完毕");
                cyclicBarrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("所有线程写入完毕,继续处理其他任务...");
            //加锁
            ZKCuratorLockUtil.acquire();
            System.out.println("线程" + Thread.currentThread().getName() + "获得分布式锁");
            try {
                Thread.sleep(2000);
                ZKCuratorLockUtil.release();
                System.out.println("线程" + Thread.currentThread().getName() + "释放分布式锁");
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("END");
        }
    }
}
  • 测试结果
线程Thread-0正在写入数据...
线程Thread-1正在写入数据...
END
线程Thread-2正在写入数据...
线程Thread-3正在写入数据...
线程Thread-1写入数据完毕,等待其他线程写入完毕
线程Thread-2写入数据完毕,等待其他线程写入完毕
线程Thread-0写入数据完毕,等待其他线程写入完毕
线程Thread-3写入数据完毕,等待其他线程写入完毕
所有线程写入完毕,继续处理其他任务...
所有线程写入完毕,继续处理其他任务...
所有线程写入完毕,继续处理其他任务...
所有线程写入完毕,继续处理其他任务...
线程Thread-3获得分布式锁
线程Thread-3释放分布式锁
END
线程Thread-1获得分布式锁
线程Thread-1释放分布式锁
END
线程Thread-2获得分布式锁
线程Thread-2释放分布式锁
END
线程Thread-0获得分布式锁
线程Thread-0释放分布式锁
END

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Kafka-13.实现-

    网络层是一个相当直接的NIO服务器,不再详细描述。 sendfile的实现是通过给MessageSet接口提供writeTo方法来完成的。这允许file-bac...

    悠扬前奏
  • Java并行-0.基本概念

    临界区表示被多个线程使用的公共资源,但是每一次只能有一个线程使用它。 比如打印机资源。

    悠扬前奏
  • Java并发-29.线程池

    悠扬前奏
  • Java计数器之CountDownLatch、CyclicBarrier、Semaphore

    在Java里面有几种可以用于控制线程状态的方法,如CountDownLatch计数器、CyclicBarrier循环栅栏、Sempahore信号量。下面就分别...

    用户1154259
  • 并发工具箱 concurrent包的原理分析以及使用

    BlockingQueue 通常用于一个线程生产对象,而另外一个线程消费这些对象的场景。下图是对这个原理的阐述:

    小勇DW3
  • caffe Ununtu 16.04.

    LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib 改为:

    py3study
  • ThreadLocal可以解决并发问题吗

    到底什么是线程的不安全?为什么会存在线程的不安全?线程的不安全其实就是多个线程并发的去操作同一共享变量没用做同步所产生意料之外的结果。那是如何体现出来的呢?我们...

    乱敲代码
  • 读书笔记《Java并发编程的艺术 - 方腾飞》- 并发的两个‘老‘问题

    上一篇文章我们认识了什么是并发编程,随着并发编程而来的则是并发带来的各种问题,死锁和资源问题,那这一篇我们继续跟着作者去看一看这两个‘老‘问题。

    lvgo
  • EventBus 原理深度解析

    在工作中,经常会遇见使用异步的方式来发送事件,或者触发另外一个动作:经常用到的框架是MQ(分布式方式通知)。如果是同一个jvm里面通知的话,就可以使用Event...

    java思维导图
  • EventBus原理深度解析

    在工作中,经常会遇见使用异步的方式来发送事件,或者触发另外一个动作:经常用到的框架是MQ(分布式方式通知)。如果是同一个jvm里面通知的话,就可以使用Event...

    黄泽杰

扫码关注云+社区

领取腾讯云代金券