Self-written Framework 4: A simple implementation of distributed locks

Source: Internet
Author: User

Distributed locks are often used to solve the problem of distributed resource access to the conflict. Start by thinking of using reentrantlock to achieve, but actually to achieve the time. It is problematic that Reentrantlock's lock and unlock requirements must be on the same thread, while in distributed applications, lock and unlock are two unrelated requests. Therefore, it is certainly not the same thread, so reentrantlock cannot be used.


Next, consider using your own state to carry out the lock status of the record, the results found always deadlock. A careful look at the code, can not lock dead.

Public synchronized void Lock () {    while (lock) {        thread.sleep (1);    }    Lock=true, ...} public synchronized void Unlock () {    lock=false; ...}


The first request asks for a lock. All right. Give him a lock, and then he takes the lock and goes to work.
this time, the second request also requires a lock, OK, he is in lock medium to be unlocked.
The first to finish the work, came back to lock, this time sad, because. He can't get into the unlock method.


Some might ask, why use while. Instead of using wait...notify? This question is left for a moment. See if anyone can give it out.
Anyway. The bin case was aborted.


Same. Do not put synchronized on the method, directly put in the method to put a synchronization object can not? The truth is the same. The same deadlock will occur.
So far the future is dark.
@ Shen Coliang Classmate's http://my.oschina.net/shenxueliang/blog/135865 wrote a with ZK to do with Bushi, feeling or is more complex and doubtful.

You can't do it yourself. And not to forget.


Then look at the lock interface, think about it, do not follow the lock interface. The following interfaces have been written.


Public interface Distributedlock extends RemoteObject {    long Lock () throws RemoteException, TimeoutException;    Long Trylock (long time, Timeunit unit) throws RemoteException, TimeoutException;    void unlock (Long token) throws remoteexception;}


Oh, sharp-eyed's classmates may have found a different.



The lock method adds a long return value. Trylock method, returned is not a Boolean. Long,unlock method is also a long reference to the number of parameters, hehe. The trick is right here.



public class Distributedlockimpl extends UnicastRemoteObject implements Distributedlock {/** * Timeout unit */priv    Ate timeunit locktimeoutunit = timeunit.seconds;    /** * Lock token */private volatile long token = 0;    /** * Synchronization Object */byte[] lock = new Byte[0]; /** * Default never timeout */long lockTimeout = 60 * 60;//default timeout 3,600 seconds long beginlocktime;//get token time.    Unit millisecond public Distributedlockimpl () throws RemoteException {super (); }/** * @param lockTimeout Lock time-out. Assuming that the locked object does not unlock, after timeout, the active unlock * @param locktimeoutunit * @throws remoteexception */public Distributedlockimpl (Lon        G LockTimeout, Timeunit locktimeoutunit) throws remoteexception {super ();        This.locktimeout = LockTimeout;    This.locktimeoutunit = This.locktimeoutunit;    } public long Lock () throws TimeoutException {return Trylock (0, timeunit.milliseconds); } private Boolean islocktimeout () {if (lockTimeout <= 0) {return fAlse;    } return (System.currenttimemillis ()-Beginlocktime) < Locktimeoutunit.tomillis (lockTimeout);        } Private Long GetToken () {beginlocktime = System.currenttimemillis ();        token = System.nanotime ();    return token; Public long Trylock (long time, Timeunit unit) throws TimeoutException {synchronized (lock) {long            StartTime = System.nanotime ();                        while (token! = 0 && islocktimeout ()) {try {if (Time > 0) {                        Long endTime = System.nanotime ();                        if (Endtime-starttime >= Unit.tomillis (time)) {throw new timeoutexception ();                }} thread.sleep (1); } catch (Interruptedexception e) {//do noting}} return GetToken        ();      }} public void unlock (long token) {  if (This.token! = 0 && token = = This.token) {this.token = 0;        } else {throw new RuntimeException ("token" + token + "invalid."); }    }}



The following is an explanation of the code.



The above code provides an Trylock method that always waits for the lock method of acquiring locks and assumes that the lock fails at the specified time to obtain the timeout exception, and another unlock method.
The key point of the technology is actually on the token, above the implementation. There is a major assumption that the time between two remote calls cannot be completed within 1 nanoseconds.

Therefore, each lock operation returns a long integer token, which is the number of nanoseconds at the time of execution. The next unlock must be unlocked with the obtained token, and the ability to succeed is sufficient. Thus, unlocking does not need to join the synchronization operation, so as to solve the problem of the above deadlock.
In fact, there is no token to be able to, but that will cause a to acquire the lock, but B execution unlock will also be successfully unlocked. is not safe. and add tokens. will be able to ensure that only the lock-in talent enough to unlock.
Here is the test code:

public class Testdlock {public static void main (string[] args) throws Exception {Rmiserver rmiserver = new Loc        Alrmiserver ();        Distributedlockimpl Distributedlock = new Distributedlockimpl ();        Rmiserver.registerremoteobject ("Lock1", Distributedlock);        Multithreadprocessor processor = new Multithreadprocessor ("AA");        for (int i = 0; i < 8; i++) {Processor.addprocessor (New Runlock ("AA" + i));        } Long S = System.currenttimemillis ();        Processor.start ();        Long e = System.currenttimemillis ();        System.out.println (e-s);    Rmiserver.unexportobject (Distributedlock);    }}class Runlock extends Abstractprocessor {public runlock (String name) {super (name); } @Override protected void action () throws Exception {try {rmiserver client = new Remotermiserve            R ();            Distributedlock lock = Client.getremoteobject ("Lock1");      for (int i = 0; i <; i++) {          Long token = Lock.lock ();            Lock.unlock (token);        } System.out.println ("end-" + thread.currentthread (). GetId ());        } catch (RemoteException e) {e.printstacktrace (); }    }}



Status of implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21st
22
23
24
25
26
27
-0 [main] INFO-thread group <aa> execution start, number of threads 8 ...
-3 [AA-AA0] INFO-Threads <aa-aa0> Execution Start ...
-3 [Aa-aa1] INFO-Threads <aa-aa1> Execution Start ...
-3 [Aa-aa2] INFO-Threads <aa-aa2> Execution Start ...
-3 [Aa-aa3] INFO-Threads <aa-aa3> Execution Start ...
-3 [AA-AA4] INFO-Threads <aa-aa4> Execution Start ...
-4 [AA-AA5] INFO-Threads <aa-aa5> Execution Start ...
-4 [AA-AA6] INFO-Threads <aa-aa6> Execution Start ...
-8 [Aa-aa7] INFO-Threads <aa-aa7> Execution Start ...
End-19
-9050 [Aa-aa3] INFO-thread <aa-aa3> execution end
End-17
-9052 [AA-AA1] INFO-thread <aa-aa1> execution end
End-20
-9056 [AA-AA4] INFO-thread <aa-aa4> execution end
End-16
-9058 [aa-aa0] INFO-thread <aa-aa0> execution end
End-21
-9059 [AA-AA5] INFO-thread <aa-aa5> execution end
End-26
-9063 [aa-aa7] INFO-thread <aa-aa7> execution end
End-18
-9064 [AA-AA2] INFO-thread <aa-aa2> execution end
End-22
-9065 [AA-AA6] INFO-thread <aa-aa6> execution end
-9066 [main] INFO-thread group <aa> execution end, spents: 9065ms
9069


also90698,000 lock and unlock operations were performed in Ms.
Summary:
Above the implementation of the distributed lock scheme, comprehensive consideration of the implementation of simple, lock security, lock timeout and other factors.

The actual test, about 900 to 1000 times the lock and release lock operation per second, to meet the majority of application requirements.

Welcome to the Open source technology community: http://bbs.tinygroup.org .

The Code and framework information in this example will be shared in the community. "Self-write framework" member QQ Group: 228977971, let's do it together. Learn the secrets of the Open source framework!

Self-written Framework 4: A simple implementation of distributed locks

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.