1. What is a distributed lock
General Lock: Generally we say the lock is but the process of multi-threaded locks, in multi-threaded concurrent programming, for data synchronization between threads, to protect the access of shared resources
Distributed Locks: Distributed lock refers to the distributed environment, protection of cross-process, cross-host, cross-network shared resources, mutually exclusive access to ensure consistency
2. Architecture diagram of distributed locks
3. Algorithm flow for distributed locks
Package com.jike.lock;
Import Java.util.concurrent.TimeUnit;
Public interface Distributedlock {
/* * Acquires the lock, if not received, Waits
*
/public void Acquire () throws Exception;
/* Gets the lock until timeout
*
/public Boolean acquire (long time, Timeunit unit) throws Exception;
/* Release lock
*
/public void release () throws Exception;
}
Package com.jike.lock;
Import java.util.Collections;
Import Java.util.Comparator;
Import java.util.List;
Import Java.util.concurrent.CountDownLatch;
Import Java.util.concurrent.TimeUnit; import org.
I0Itec.zkclient.IZkDataListener; import org.
I0Itec.zkclient.ZkClient; import org.
I0Itec.zkclient.exception.ZkNoNodeException;
public class Basedistributedlock {private final zkclientext client;
Private final String path;
The path of the locker node in zookeeper private final String BasePath;
Private final String Lockname;
private static final Integer Max_retry_count = 10;
Public Basedistributedlock (Zkclientext client, string path, String lockname) {this.client = client;
This.basepath = path;
This.path = Path.concat ("/"). Concat (Lockname);
This.lockname = Lockname;
} private void Deleteourpath (String ourpath) throws exception{Client.delete (Ourpath); private string Createlocknode (zkclient client, String path) throws Exception{return client.createephemeralsequential (path, NULL); Private Boolean Waittolock (Long Startmillis, long millistowait, String Ourpath) throws exception{Boolean
Havethelock = false;
Boolean doDelete = false; try {while (!havethelock) {//Gets all nodes under the lock node List<str
ing> children = Getsortedchildren ();
String sequencenodename = ourpath.substring (Basepath.length () +1);
Gets the position of the current node in the list of all nodes int ourindex = Children.indexof (sequencenodename); The node location is less than 0, stating that the node if (ourindex<0) {throw new Zknonodeexception ("Node not found") is not found: "+ Sequenc
Enodename); }//node location greater than 0 description There are other nodes in front of the current node that need to wait for other nodes to release Boolean isgetthelock = Ourindex
= = 0; String Pathtowatch = Isgetthelock?
Null:children.get (ourIndex-1); if (isgetthelock) {Havethelock = true; }else{/** * Gets the minor node of the current node and listens for changes in the node */stri
ng Previoussequencepath = basepath. Concat ("/"). Concat (Pathtowatch);
Final Countdownlatch latch = new Countdownlatch (1); Final Izkdatalistener Previouslistener = new Izkdatalistener () {public void Handleda
tadeleted (String dataPath) throws Exception {Latch.countdown ();
The public void Handledatachange (String dataPath, Object data) throws Exception {
Ignore}}; try {//If the node does not exist an exception will occur client.subscribedatachanges (Previou Ssequencepath, PreviouSlistener); if (millistowait! = null) {millistowait-= (System.currenttimemilli
S ()-startmillis);
Startmillis = System.currenttimemillis (); if (millistowait <= 0) {DoDelete = true;
Timed out-delete our node break;
} latch.await (millistowait, timeunit.microseconds);
} else {latch.await (); }} catch (Zknonodeexception e) {/ /ignore}finally{client.unsubscribedatachanges (Previoussequencepath, Previouslis
Tener); }}}} catch (Exception e) {//exception required to delete node
DoDelete = true;
Throw e; } finally {//If you need to delete the node if (doDelete) {Deleteourpath
(Ourpath);
}} return havethelock;
} private string Getlocknodenumber (String str, string lockname) {int index = Str.lastindexof (lockname);
if (index >= 0) {index + = lockname.length (); return index <= str.length ()?
Str.substring (Index): "";
} return str; } list<string> Getsortedchildren () throws Exception {try{list<string> childre
n = Client.getchildren (basepath);
Collections.sort (Children, new comparator<string> () {
public int Compare (string lhs, string rhs) {return Getlocknodenumber (LHS, Lockname). CompareTo (Getlocknodenumber (RHS, Lockname))
;
}
}
);
return children;
}catch (zknonodeexception e) {client.createpersistent (BasePath, true);
return Getsortedchildren ();
}} protected void ReleaseLock (String lockpath) throws exception{Deleteourpath (Lockpath); /** * Try to acquire the lock * @param time * @param unit * @return * @throws Exception */protected String Attemptlock (lo
ng time, Timeunit unit) throws exception{final long Startmillis = System.currenttimemillis (); Final Long millistowait = (unit! = NULL)?
Unit.tomillis (time): null;
String ourpath = null;
Boolean hasthelock = false;
Boolean isDone = false;
int retrycount = 0;
Network Flash needs to retry a try while (!isdone) { IsDone = true;
try {Ourpath = createlocknode (client, path);
Hasthelock = Waittolock (Startmillis, millistowait, Ourpath);
} catch (Zknonodeexception e) {if (retrycount++ < Max_retry_count)
{IsDone = false;
} else {throw e;
}}} if (Hasthelock) {return ourpath;
} return null;
}
}
Package com.jike.lock; import org.
I0Itec.zkclient.serialize.BytesPushThroughSerializer; public class Testdistributedlock {public static void main (string[] args) {final Zkclientext zkClientExt1 = new Z
Kclientext ("192.168.1.105:2181", the New Bytespushthroughserializer ());
Final Simpledistributedlockmutex mutex1 = new Simpledistributedlockmutex (ZKCLIENTEXT1, "/mutex");
Final Zkclientext zkClientExt2 = new Zkclientext ("192.168.1.105:2181", the New Bytespushthroughserializer ());
Final Simpledistributedlockmutex mutex2 = new Simpledistributedlockmutex (zkClientExt2, "/mutex");
try {mutex1.acquire ();
System.out.println ("Client1 locked");
Thread CLIENT2THD = new Thread (new Runnable () {public void run () {try {mutex2.acquire ();
System.out.println ("Client2 locked");
Mutex2.release ();
System.out.println ("Client2 released lock");
} catch (Exception e) {e.printstacktrace ();
}}
});
Client2thd.start ();
Thread.Sleep (5000);
Mutex1.release ();
System.out.println ("Client1 released lock");
Client2thd.join ();
} catch (Exception e) {e.printstacktrace ();
}
}
}