分布鎖實(shí)現(xiàn)方案和優(yōu)缺點(diǎn)先占坑
鎖重入待實(shí)現(xiàn)!!初斑!
//核心邏輯
tryLock():搶鎖
1 創(chuàng)建臨時(shí)序列節(jié)點(diǎn),創(chuàng)建后阻塞,
2 zk.create()成功后蔫耽,在回調(diào)函數(shù)中,通過(guò)zk.getChildren()獲取當(dāng)前根目錄下序列節(jié)點(diǎn)帕棉,
3 在回調(diào)函數(shù)中判斷自己是否是第一節(jié)點(diǎn)针肥,是則獲得鎖,不是香伴,則watch前一個(gè)節(jié)點(diǎn)慰枕,
4 如果前一個(gè)節(jié)點(diǎn)被刪除,則zk.getChildren()即纲,重復(fù)3具帮,4步驟;
work(): 搶鎖成功后的業(yè)務(wù)邏輯
unLock():釋放鎖
遺留問(wèn)題低斋,如何設(shè)計(jì)鎖重入蜂厅?
/**
* @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(){
//創(chuàng)建序列節(jié)點(diǎn)
try {
System.out.println(threadName + "create lock ....");
zk.create("/lock",threadName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,this,"AsyncCallback.StringCallback");
//阻塞,搶鎖膊畴,搶鎖操作在回調(diào)函數(shù)中完成
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) {
//如果第一個(gè)哥們掘猿,那個(gè)鎖釋放了,其實(shí)只有第二個(gè)收到了回調(diào)事件4娇纭稠通!
//如果衬衬,不是第一個(gè)哥們,某一個(gè)改橘,掛了滋尉,也能造成他后邊的收到這個(gè)通知,從而讓他后邊那個(gè)跟去watch掛掉這個(gè)哥們前邊的飞主。狮惜。。
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;
//節(jié)點(diǎn)創(chuàng)建成功碌识,需要查看自己得序列號(hào) 判斷是否獲得鎖
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 上一個(gè)序列點(diǎn)
zk.exists("/"+children.get(i-1),this, this,"Children2Callback");
}
}
//AsyncCallback.StatCallback
@Override
public void processResult(int rc, String path, Object ctx, Stat stat) {
}
}