-
Notifications
You must be signed in to change notification settings - Fork 4
/
RedisDistributedLock.java
136 lines (121 loc) · 4.55 KB
/
RedisDistributedLock.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package simpleDistLockTest;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* 基于redis的分布式锁
*
* @author Xiupitter
*
*/
public class RedisDistributedLock implements Lock{
private static JedisPool pool;
private String key;
private long timeout;
static{
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxActive(30);
poolConfig.setMinIdle(30);
poolConfig.setMinEvictableIdleTimeMillis(500);
poolConfig.setTestOnBorrow(true);
pool = new JedisPool(poolConfig, "192.168.192.128", 6379);
}
public static JedisPool getJedisPool(){
return pool;
}
/**
* @param key 分布式锁必须基于一个key,该key就是竞争资源,本地锁lock本身就是竞争资源,远程锁必须有个key表示锁的本体是在远程的,并且锁的竞争
* 资源就是该key,一般为string这样所有分布式节点都可以简单的通过该string获得锁
* @param lockTimeout 锁过期时间,如果一个进程没有unlock,则其他人无法进入锁,所以需要一个过期时间
*/
public RedisDistributedLock(String key,long lockTimeout){
this.key =key;
this.timeout =lockTimeout;
}
@Override
public synchronized void lock() {
// TODO Auto-generated method stub
Jedis j = RedisDistributedLock.getJedisPool().getResource();
while(j.setnx("lock."+key, String.valueOf(System.currentTimeMillis()+timeout+1))!=1){
if((Long.parseLong(j.get("lock."+key))<System.currentTimeMillis()+1)&&//检测是否超时
(Long.parseLong(j.getSet("lock."+key, String.valueOf(System.currentTimeMillis()+timeout+1)))<System.currentTimeMillis()+1)){
break;
}
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
RedisDistributedLock.getJedisPool().returnResource(j);
}
@Override
public synchronized void lockInterruptibly() throws InterruptedException {
// TODO Auto-generated method stub
Jedis j = RedisDistributedLock.getJedisPool().getResource();
while(j.setnx("lock."+key, String.valueOf(System.currentTimeMillis()+timeout+1))!=1){
if(Long.parseLong(j.get("lock."+key))<System.currentTimeMillis()+1&&
(Long.parseLong(j.getSet("lock."+key, String.valueOf(System.currentTimeMillis()+timeout+1)))<System.currentTimeMillis()+1)){
break;
}
Thread.sleep(20);
}
RedisDistributedLock.getJedisPool().returnResource(j);
}
@Override
public synchronized boolean tryLock() {
// TODO Auto-generated method stub
Jedis j = RedisDistributedLock.getJedisPool().getResource();
if(j.setnx("lock."+key, String.valueOf(System.currentTimeMillis()+timeout+1))!=1){
if(Long.parseLong(j.get("lock."+key))<System.currentTimeMillis()+1&&
(Long.parseLong(j.getSet("lock."+key, String.valueOf(System.currentTimeMillis()+timeout+1)))<System.currentTimeMillis()+1)){
RedisDistributedLock.getJedisPool().returnResource(j);
return true;
}
RedisDistributedLock.getJedisPool().returnResource(j);
return false;
}else{
RedisDistributedLock.getJedisPool().returnResource(j);
return true;
}
}
@Override
public synchronized boolean tryLock(long time, TimeUnit unit)
throws InterruptedException {
// TODO Auto-generated method stub
long timeAccumulate = 0;
Jedis j = RedisDistributedLock.getJedisPool().getResource();
while(j.setnx("lock."+key, String.valueOf(System.currentTimeMillis()+timeout+1))!=1){
if(Long.parseLong(j.get("lock."+key))<System.currentTimeMillis()+1&&
(Long.parseLong(j.getSet("lock."+key, String.valueOf(System.currentTimeMillis()+timeout+1)))<System.currentTimeMillis()+1)){//过期锁
RedisDistributedLock.getJedisPool().returnResource(j);
return true;
}
if(timeAccumulate>unit.toNanos(time)){
RedisDistributedLock.getJedisPool().returnResource(j);
return false;
}
Thread.sleep(20);
timeAccumulate+=20*1000000;
}
RedisDistributedLock.getJedisPool().returnResource(j);
return true;
}
@Override
public synchronized void unlock() {
// TODO Auto-generated method stub
Jedis j = RedisDistributedLock.getJedisPool().getResource();
if(System.currentTimeMillis()<Long.parseLong(j.get("lock."+key)))//it is not timeout,so
j.del("lock."+key);
RedisDistributedLock.getJedisPool().returnResource(j);
}
@Override
public synchronized Condition newCondition() {
// TODO Auto-generated method stub
return null ;
}
}