分布锁实现方案和优缺点先占坑
锁重入待实现!!!
//核心逻辑
tryLock():抢锁
1 创建临时序列节点,创建后阻塞,
2 zk.create()成功后,在回调函数中,通过zk.getChildren()获取当前根目录下序列节点,
3 在回调函数中判断自己是否是第一节点,是则获得锁,不是,则watch前一个节点,
4 如果前一个节点被删除,则zk.getChildren(),重复3,4步骤;
work(): 抢锁成功后的业务逻辑
unLock():释放锁
遗留问题,如何设计锁重入?
/**
* @author haowq 2021/4/7 14:58
*/
public class WatchCallback implements Watcher, AsyncCallback.StringCallback, AsyncCallback.Children2Callback , AsyncCallback.StatCallback {
private ZooKeeper zk;
private String pathName;
private String threadName;
//Getter Setter
private CountDownLatch latch = new CountDownLatch(1);
public ZooKeeper getZk() {
return zk;
}
public void setZk(ZooKeeper zk) {
this.zk = zk;
}
public void tryLock(){
//创建序列节点
try {
System.out.println(threadName + "create lock ....");
zk.create("/lock",threadName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,this,"AsyncCallback.StringCallback");
//阻塞,抢锁,抢锁操作在回调函数中完成
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void unLock(){
try {
zk.delete(pathName,-1);
System.out.println(threadName + " over work....");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (KeeperException e) {
e.printStackTrace();
}
}
public void process(WatchedEvent event) {
//如果第一个哥们,那个锁释放了,其实只有第二个收到了回调事件!!
//如果,不是第一个哥们,某一个,挂了,也能造成他后边的收到这个通知,从而让他后边那个跟去watch挂掉这个哥们前边的。。。
switch (event.getType()) {
case None:
case NodeDataChanged:
case NodeChildrenChanged:
case NodeCreated:
break;
case NodeDeleted:
zk.getChildren("/",false,this ,"syncCallback.Children2Callbac");
break;
}
}
// AsyncCallback.StringCallback
@Override
public void processResult(int rc, String path, Object ctx, String name) {
System.out.println(name);
pathName = name;
//节点创建成功,需要查看自己得序列号 判断是否获得锁
zk.getChildren(pathName,this,this,"Children2Callback");
}
//AsyncCallback.Children2Callbac
@Override
public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
//查看自己的序列
Collections.sort(children);
String substring = path.substring(1);
int i = children.indexOf(substring);
//如果序列最小 获得锁
if(i ==0){
//yes
System.out.println(threadName +" i am first....");
try {
zk.setData("/",threadName.getBytes(),-1);
latch.countDown();
} catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
}else{
//Watch 上一个序列点
zk.exists("/"+children.get(i-1),this, this,"Children2Callback");
}
}
//AsyncCallback.StatCallback
@Override
public void processResult(int rc, String path, Object ctx, Stat stat) {
}
}