Simple implementation of distributed locks

Source: Internet
Author: User
Tags time in milliseconds

Distributed lock is often used in distributing applications, mainly to solve the problem of distributed resource access conflict. The first thing to think about is reentrantlock, but in reality it's problematic, reentrantlock lock and unlock requirements must be on the same thread, and in distributed applications, lock and unlock are two unrelated requests, Therefore, it is certainly not the same thread, so reentrantlock cannot be used.
Then consider the use of their own state to carry out the lock state record, the results found always deadlock, carefully look at the code, can not lock dead.

1
2
3
4
5
6
7
8
9
10
11
12
Public synchronized void Lock () {
while (lock) {
Thread.Sleep (1);
}
Lock=true;
...
}

public synchronized void unlock () {
Lock=false;
...
}



The first request asks for a lock, okay, 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, come over and lock, this time sad, because, he can't enter unlock method.
One might ask, why use while instead of wait...notify? This question, let's see if anyone can give it up.
In short, the above bin case miscarried.
Similarly, do not put synchronized on the method, directly put in the method to put a synchronization object can not? The same goes for the same deadlock.
So far the future is dark.
@ Shen Coliang Classmate's http://my.oschina.net/shenxueliang/blog/135865 wrote a with ZK do with Bushi, feeling is more complex and doubtful. Do not do it yourself, and do not forget.
Then look at the lock interface, think about it, do not follow the lock interface. The following interface has been written.

1
2
3
4
5
6
7
8
9
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, return is not a Boolean, is also the Long,unlock method more than a long parameter type parameter, oh, the technique is here.

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
public class Distributedlockimpl extends UnicastRemoteObject implements Distributedlock {
/**
* Timeout units
*/
Private Timeunit locktimeoutunit = timeunit.seconds;
/**
* Lock Tokens
*/
Private volatile long token = 0;
/**
* Synchronizing objects
*/
Byte[] lock = new Byte[0];
/**
* Default never Expires
*/
Long lockTimeout = 60 * 60;//default timeout 3,600 seconds
Long beginlocktime;//gets token time in milliseconds


Public Distributedlockimpl () throws RemoteException {
Super ();
}


/**
* @param lockTimeout Lock timeout time, if lock object unlocked, automatically unlock after timeout
* @param locktimeoutunit
* @throws RemoteException
*/
Public Distributedlockimpl (Long 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.");
}
}
}



Here's a little bit of code to explain.

The code above provides a lock method that waits forever for a lock and a trylock method to get the timeout exception if the lock fails at the specified time, and there is another unlock method.
The key point of the technology is actually the token, the above implementation, there is a basic assumption that the time between two remote calls can not 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 before it can be successful. Thus, unlocking does not need to add synchronization operations, so as to resolve the above deadlock problem.
In fact, there is no token is also possible, but that will result in a acquires a lock, but B execution unlock will also be successfully unlocked, is not secure, and the addition of tokens, you can guarantee that only the lock can be unlocked.
Here is the test code:

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
28
29
30
31
32
33
34
35
36
37
public class Testdlock {
public static void Main (string[] args) throws Exception {
Rmiserver rmiserver = new Localrmiserver ();
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 Remotermiserver ();
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 ();
}
}
}



Operating conditions:

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> run start, number of threads 8 ...
-3 [aa-aa0] INFO-thread <aa-aa0> run start ...
-3 [AA-AA1] INFO-thread <aa-aa1> run start ...
-3 [AA-AA2] INFO-thread <aa-aa2> run start ...
-3 [Aa-aa3] INFO-thread <aa-aa3> run start ...
-3 [AA-AA4] INFO-thread <aa-aa4> run start ...
-4 [AA-AA5] INFO-thread <aa-aa5> run start ...
-4 [AA-AA6] INFO-thread <aa-aa6> run start ...
-8 [aa-aa7] INFO-thread <aa-aa7> run start ...
End-19
-9050 [Aa-aa3] INFO-thread <aa-aa3> run end
End-17
-9052 [AA-AA1] INFO-thread <aa-aa1> run end
End-20
-9056 [AA-AA4] INFO-thread <aa-aa4> run end
End-16
-9058 [aa-aa0] INFO-thread <aa-aa0> run end
End-21
-9059 [AA-AA5] INFO-thread <aa-aa5> run end
End-26
-9063 [aa-aa7] INFO-thread <aa-aa7> run end
End-18
-9064 [AA-AA2] INFO-thread <aa-aa2> run end
End-22
-9065 [AA-AA6] INFO-thread <aa-aa6> run end
-9066 [main] INFO-thread group <aa> run end, spents: 9065ms
9069



That is, 8,000 locks and unlocks are performed in 9069ms.
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 for lock and release lock operations per second, can meet most application requirements.
As a result of yesterday powder request issued as soon as possible, so the more hurried, deficiencies and bugs are unavoidable, welcome to shoot bricks.

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.