public class TestLock {
public static void main(String[] args) {
ZkClient zkClient1 = new ZkClient(new ZkConnection("127.0.0.1:2181"), 10000);
String path = "/exclusive_lock";
if(!zkClient1.exists(path)) {
zkClient1.createPersistent(path, "root");
} else {
System.out.println("/exclusive_lock 路径已经存在, 开始删除");
zkClient1.delete("/exclusive_lock");
System.out.println("/exclusive_lock 路径已经存在, 删除成功");
}
if(zkClient1.exists("/exclusive_lock")) {
System.out.println("/exclusive_lock 路径已经存在");
} else {
System.out.println("/exclusive_lock 路径不存在");
}
}
}
/exclusive_lock 路径已经存在
/exclusive_lock 路径已经存在, 开始删除
/exclusive_lock 路径已经存在, 删除成功
/exclusive_lock 路径不存在
zkClient1.deleteRecursive("/exclusive_lock");
利用zookeeper的这个特性,我们可以实现分布式锁,保证高并发环境下CAP中的CP特性。
先实现一个简化版的分布式锁,只有加锁和释放锁两个方法。
public class DistributedLock {
public boolean tryLock(ZkClient zkClient, String path, String value) {
try {
zkClient.createPersistent(path, value);
} catch (Exception e) {
return false;
}
return true;
}
public void releaseLock(ZkClient zkClient, String path) {
zkClient.deleteRecursive(path);
}
}
写一个线程任务,方便后面做并发测试。
@Getter
@Setter
public class Task implements Runnable {
private String path;
private String value;
private ZkClient zkClient;
public Task(ZkClient zkClient, String path, String value) {
this.zkClient = zkClient;
this.path = path;
this.value = value;
}
public void run() {
DistributedLock distributedLock = new DistributedLock();
if(distributedLock.tryLock(zkClient, path, value)){
System.out.println(Thread.currentThread().getName()+"加锁成功, 开始做任务了");
try {
Thread.currentThread().sleep(10000L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"做了一段时间任务,完成了开始释放锁");
distributedLock.releaseLock(zkClient, path);
} else {
System.out.println(Thread.currentThread().getName()+"加锁失败, 休息一下吧");
try {
Thread.currentThread().sleep(10000L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
继续在前面的测试锁的类中进行测试,这里前提条件是已经建好了exclusive_lock 这个path,然后需要在这个path下建立lock子路径,通过多个线程同时并发创建,看是否能保证只建立唯一的lock子路径。
public static void main(String[] args) {
ZkClient zkClient1 = new ZkClient(new ZkConnection("127.0.0.1:2181"), 10000);
String path = "/exclusive_lock";
zkClient1.createPersistent(path, "root");
ExecutorService executorService = Executors.newFixedThreadPool(2);
for(int i=0; i<2; i++){
executorService.submit(new Task(zkClient1, "/exclusive_lock/lock", "lock"));
} }
跑出的结果:
pool-1-thread-2加锁成功, 开始做任务了
pool-1-thread-1加锁失败, 休息一下吧
pool-1-thread-2做了一段时间任务,完成了开始释放锁
从执行结果来看,zookeeper能够保证分布式环境下只有一个线程获取锁,并且也能成功释放锁,这次先分享到这里,下回将分享如何对锁进行监控,在持有锁的线程释放后,其他的线程能得到通知重新竞争锁。