一,阻塞式和非阻塞式
“阻塞”和“非阻塞”只是一个人为的概念,“阻塞”说的是一个线程去尝试获取锁,如果失败,就阻塞在这里,监听到持有锁的线程释放,再次去尝试获取。 而“非阻塞”是我尝试一次失败了,失败就拉倒,直接不要了。
而这两个区别是通过代码来体现的。
二,zk非阻塞式锁的实现
(1)首先定义“锁”的接口,包括上锁,解锁,锁是否存在。
public interface ZkLocker {
/**
* 能否上锁成功
*/
boolean lock();
/**
* 解锁 能否解锁成功
*/
boolean unlock();
/**
* 判断锁是否存在
*/
boolean exists();
}
(2)定义基类,包含对于zookeeper结点的一些基本操作,包括和zk连接,创建结点,删除结点...等等。所有的锁(不管什么锁都要继承这个类)
public class ZkLockerBase {
//客户端和服务端连接
protected ZooKeeper zooKeeper;
//锁的根节点的名称
protected String rootNodeName = "/zk-lock";
//锁的名称
protected String lockName;
/**
* 默认连接到指定的服务端
* @throws IOException
* @throws InterruptedException
*/
public ZkLockerBase() {
this("localhost:2181");//服务器ip地址,改。
}
public ZkLockerBase(String connectString){
try {
CountDownLatch latch = new CountDownLatch(1);
zooKeeper = new ZooKeeper(connectString, 5000000, new Watcher() {
@Override
public void process(WatchedEvent event) {
switch (event.getType()) {
case None:
if (event.getState().equals(Event.KeeperState.SyncConnected)) {
latch.countDown();
}
break;
case NodeCreated:
break;
case NodeDeleted:
break;
case NodeChildrenChanged:
break;
}
}
});
latch.await();
createRootNode();//连接之后创建根节点
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 创建根节点,用于存放所有的节点或者子节点实现的锁
*/
public void createRootNode(){
//判断我的root是否存在
if (!exists(rootNodeName)){
createNode(rootNodeName,CreateMode.CONTAINER);
}
}
public boolean exists(String nodeName){
try {
Stat exists = zooKeeper.exists(nodeName, false);
return exists != null;
}catch (Exception e){
}
return false;
}
/**
* return真正的名字
* @param nodeName 创建结点名字
* @param createMode 创建结点的类型
* @return 创建成功之后结点的名字
*/
public String createNode(String nodeName, CreateMode createMode) {
try {
return zooKeeper.create(nodeName, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);
}catch (Exception e){
e.printStackTrace();
return null;//创建失败
}
}
/**
* 删除结点
* @param nodeName
* @return
*/
public boolean deleteNode(String nodeName){
try {
zooKeeper.delete(nodeName,-1);//跳过版本检查
return true;
}catch (Exception e){
e.printStackTrace();
}
return false;
}
}
(3)zk非阻塞式锁实现
public class ZkNodeNoneBlockingLock extends ZkLockerBase implements ZkLocker {
/**
* 默认连接
* @param lockName
*/
public ZkNodeNoneBlockingLock(String lockName){
super();
this.lockName = lockName;
}
/**
* 可指定连接
* @param connectString
* @param lockName
*/
public ZkNodeNoneBlockingLock(String connectString,String lockName){
super(connectString);
this.lockName = lockName;
}
@Override
public boolean lock() {
return createNode(rootNodeName + "/" + lockName,
CreateMode.EPHEMERAL) != null;
}
@Override
public boolean unlock() {
return deleteNode(rootNodeName + "/" + lockName);
}
@Override
public boolean exists() {
return exists(rootNodeName + "/" + lockName);
}
}
接下来跑测试代码来测试,分别测试在单线程和多线程并发状态下的结果。
测试代码:
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » zookeeper子结点方式实现分布式锁(阻塞,非阻塞)
发表评论 取消回复