周浩 9 лет назад
Родитель
Сommit
d3b7140265

+ 2 - 2
hsweb-web-concurrent/hsweb-web-concurrent-lock/src/main/java/org/hsweb/concurrent/lock/support/AnnotationLockAopAdvice.java

@@ -49,12 +49,12 @@ public class AnnotationLockAopAdvice {
             }
         }
         try {
-            logger.debug("try lock :", name);
+            logger.debug("try lock :{}", name);
             boolean locked = _lock.tryLock(lock.waitTime(), lock.timeUnit());
             if (!locked) throw new LockException(name + "error");
             return pjp.proceed();
         } finally {
-            logger.debug("unlock :", name);
+            logger.debug("unlock :{}", name);
             unlock(_lock);
         }
     }

+ 25 - 15
hsweb-web-concurrent/hsweb-web-concurrent-lock/src/main/java/org/hsweb/concurrent/lock/support/redis/RedisLock.java

@@ -1,6 +1,5 @@
 package org.hsweb.concurrent.lock.support.redis;
 
-import org.hsweb.concurrent.lock.exception.LockException;
 import org.springframework.data.redis.core.RedisCallback;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.util.Assert;
@@ -15,8 +14,10 @@ import java.util.concurrent.locks.Lock;
 public class RedisLock implements Lock {
 
     static final String PREFIX = "lock:";
-    static final byte[] LOCK_VALUE = new byte[0];
-
+    static final long DEFAULT_EXPIRE = 60;
+    private long lockKeyExpireTime = DEFAULT_EXPIRE;
+    private long waitTime = 30;
+    protected byte[] lockValue;
     private RedisTemplate redisTemplate;
     private String key;
 
@@ -29,6 +30,7 @@ public class RedisLock implements Lock {
         Assert.notNull(redisTemplate);
         this.key = key;
         this.redisTemplate = redisTemplate;
+        lockValue = new byte[0];
     }
 
     @Override
@@ -36,8 +38,11 @@ public class RedisLock implements Lock {
         redisTemplate.execute((RedisCallback<Boolean>) connection -> {
             boolean locked = false;
             do {
-                locked = connection.setNX(getKey(), LOCK_VALUE);
-                sleep();
+                locked = connection.setNX(getKey(), lockValue);
+                if (locked) {
+                    connection.expire(getKey(), lockKeyExpireTime);
+                } else
+                    sleep();
             } while (!locked);
             return true;
         });
@@ -45,17 +50,22 @@ public class RedisLock implements Lock {
 
     @Override
     public void lockInterruptibly() throws InterruptedException {
-        boolean locked = (Boolean) redisTemplate.execute((RedisCallback<Boolean>) connection ->
-                        connection.setNX(getKey(), LOCK_VALUE)
-        );
+        boolean locked = (Boolean) redisTemplate.execute((RedisCallback<Boolean>) connection -> {
+            boolean l = connection.setNX(getKey(), lockValue);
+            if (l) connection.expire(getKey(), lockKeyExpireTime);
+            return l;
+        });
         if (!locked) throw new InterruptedException(new String(getKey()) + " is locked!");
     }
 
     @Override
     public boolean tryLock() {
-        return (Boolean) redisTemplate.execute((RedisCallback<Boolean>) connection ->
-                        connection.setNX(getKey(), LOCK_VALUE)
-        );
+        try {
+            lockInterruptibly();
+            return true;
+        } catch (InterruptedException e) {
+            return false;
+        }
     }
 
     @Override
@@ -65,9 +75,9 @@ public class RedisLock implements Lock {
             boolean locked = false;
             long startWith = System.nanoTime();
             do {
-                locked = connection.setNX(getKey(), LOCK_VALUE);
+                locked = connection.setNX(getKey(), lockValue);
                 if (locked) {
-                    connection.expire(getKey(), 30);
+                    connection.expire(getKey(), lockKeyExpireTime);
                     return true;
                 }
                 long now = System.nanoTime();
@@ -92,12 +102,12 @@ public class RedisLock implements Lock {
 
     @Override
     public Condition newCondition() {
-        throw new LockException("method not support");
+        throw new UnsupportedOperationException();
     }
 
     protected void sleep() {
         try {
-            Thread.sleep(10);
+            Thread.sleep(waitTime);
         } catch (InterruptedException e) {
         }
     }

+ 68 - 33
hsweb-web-concurrent/hsweb-web-concurrent-lock/src/main/java/org/hsweb/concurrent/lock/support/redis/RedisReadWriteLock.java

@@ -4,6 +4,7 @@ import org.springframework.data.redis.core.RedisCallback;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.util.Assert;
 
+import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
@@ -14,13 +15,14 @@ import java.util.concurrent.locks.ReadWriteLock;
  */
 public class RedisReadWriteLock implements ReadWriteLock {
     static final String PREFIX = "lock:";
-    static final byte[] LOCK_VALUE = new byte[0];
-
+    static final long DEFAULT_EXPIRE = 60;
     private ReadLock readLock;
-
     private WriteLock writeLock;
-
     private String key;
+    private long lockKeyExpireTime = DEFAULT_EXPIRE;
+    private long waitTime = 30;
+    protected byte[] lockValue;
+    private byte[] readLockKey, writeLockKey;
 
     private RedisTemplate redisTemplate;
 
@@ -31,6 +33,9 @@ public class RedisReadWriteLock implements ReadWriteLock {
         this.redisTemplate = redisTemplate;
         readLock = new ReadLock();
         writeLock = new WriteLock();
+        readLockKey = (PREFIX + key + ".read.lock").getBytes();
+        writeLockKey = (PREFIX + key + ".write.lock").getBytes();
+        lockValue = (UUID.randomUUID().toString()).getBytes();
     }
 
     @Override
@@ -44,32 +49,44 @@ public class RedisReadWriteLock implements ReadWriteLock {
     }
 
     private byte[] getReadKey() {
-        return (PREFIX + key + ".read.lock").getBytes();
+        return readLockKey;
     }
 
     private byte[] getWriteKey() {
-        return (PREFIX + key + ".write.lock").getBytes();
+        return writeLockKey;
     }
 
     protected void sleep() {
         try {
-            Thread.sleep(10);
+            Thread.sleep(waitTime);
         } catch (InterruptedException e) {
         }
     }
 
+    public void setWaitTime(long waitTime) {
+        this.waitTime = waitTime;
+    }
+
+    public void setLockKeyExpireTime(long lockKeyExpireTime) {
+        this.lockKeyExpireTime = lockKeyExpireTime;
+    }
+
     class ReadLock implements Lock {
+        public byte[] lockValue() {
+            return new String(lockValue).concat(Thread.currentThread().getId() + "").getBytes();
+        }
+
         @Override
         public void lock() {
             redisTemplate.execute((RedisCallback<String>) connection -> {
                 boolean locked = false;
                 do {
-                    locked = connection.exists(getWriteKey());
-                    if (!locked) {
-                        connection.setNX(getReadKey(), LOCK_VALUE);
+                    if (!connection.exists(getWriteKey())) {
+                        connection.setNX(getReadKey(), lockValue());
+                        connection.expire(getReadKey(), lockKeyExpireTime);
                         locked = true;
-                    }
-                    sleep();
+                    } else
+                        sleep();
                 } while (!locked);
                 return null;
             });
@@ -81,7 +98,9 @@ public class RedisReadWriteLock implements ReadWriteLock {
             {
                 boolean writeLocked = connection.exists(getWriteKey());
                 if (!writeLocked) {
-                    connection.setNX(getReadKey(), LOCK_VALUE);
+                    if (connection.setNX(getReadKey(), lockValue)) {
+                        connection.expire(getReadKey(), lockKeyExpireTime);
+                    }
                     writeLocked = true;
                 }
                 return writeLocked;
@@ -92,8 +111,12 @@ public class RedisReadWriteLock implements ReadWriteLock {
         @Override
         public boolean tryLock() {
             return (Boolean) redisTemplate.execute((RedisCallback<Boolean>) connection ->
-                            connection.setNX(getReadKey(), LOCK_VALUE)
-            );
+            {
+                if (connection.setNX(getReadKey(), lockValue)) {
+                    connection.expire(getReadKey(), lockKeyExpireTime);
+                }
+                return false;
+            });
         }
 
         @Override
@@ -103,10 +126,9 @@ public class RedisReadWriteLock implements ReadWriteLock {
                 boolean locked = false;
                 long startWith = System.nanoTime();
                 do {
-                    locked = connection.exists(getWriteKey());
-                    if (!locked) {
-                        connection.setNX(getReadKey(), LOCK_VALUE);
-                        connection.expire(getReadKey(), 30);
+                    if (!connection.exists(getWriteKey())) {
+                        connection.setNX(getReadKey(), lockValue);
+                        connection.expire(getReadKey(), lockKeyExpireTime);
                         return true;
                     }
                     long now = System.nanoTime();
@@ -116,22 +138,30 @@ public class RedisReadWriteLock implements ReadWriteLock {
                     }
                     sleep();
                 } while (!locked);
-                return null;
+                return false;
             });
             if (error[0] == 1) {
-                throw new InterruptedException("lock time out!");
+                throw new InterruptedException("try lock time out!");
             }
             return success;
         }
 
         @Override
         public void unlock() {
-            redisTemplate.execute((RedisCallback) conn -> conn.del(getReadKey()));
+            redisTemplate.execute((RedisCallback) conn -> {
+                byte[] lock = conn.get(getReadKey());
+                if (lock == null) return null;
+                //当前读锁为自己持有 才解锁
+                if (new String(lock).equals(new String(lockValue()))) {
+                    conn.del(getReadKey());
+                }
+                return null;
+            });
         }
 
         @Override
         public Condition newCondition() {
-            return null;
+            throw new UnsupportedOperationException();
         }
     }
 
@@ -143,9 +173,10 @@ public class RedisReadWriteLock implements ReadWriteLock {
                 do {
                     readLocked = connection.exists(getReadKey());
                     if (!readLocked) {
-                        locked = connection.setNX(getWriteKey(), LOCK_VALUE);
-                    }
-                    sleep();
+                        locked = connection.setNX(getWriteKey(), lockValue);
+                        connection.expire(getWriteKey(), lockKeyExpireTime);
+                    } else
+                        sleep();
                 } while (!locked);
                 return null;
             });
@@ -157,7 +188,9 @@ public class RedisReadWriteLock implements ReadWriteLock {
             {
                 boolean readLocked = connection.exists(getReadKey());
                 if (!readLocked) {
-                    return connection.setNX(getWriteKey(), LOCK_VALUE);
+                    boolean _locked = connection.setNX(getWriteKey(), lockValue);
+                    if (_locked) connection.expire(getWriteKey(), lockKeyExpireTime);
+                    return _locked;
                 }
                 return false;
             });
@@ -168,7 +201,10 @@ public class RedisReadWriteLock implements ReadWriteLock {
         public boolean tryLock() {
             return (Boolean) redisTemplate.execute((RedisCallback<Boolean>) connection -> {
                 if (connection.exists(getReadKey())) return false;
-                return connection.setNX(getWriteKey(), LOCK_VALUE);
+                boolean locked = connection.setNX(getWriteKey(), lockValue);
+                if (locked)
+                    connection.expire(getWriteKey(), lockKeyExpireTime);
+                return locked;
             });
         }
 
@@ -179,11 +215,10 @@ public class RedisReadWriteLock implements ReadWriteLock {
                 boolean locked = false;
                 long startWith = System.nanoTime();
                 do {
-                    locked = connection.exists(getReadKey());
-                    if (!locked) {
-                        locked = connection.setNX(getWriteKey(), LOCK_VALUE);
+                    if (!connection.exists(getReadKey())) {
+                        locked = connection.setNX(getWriteKey(), lockValue);
                         if (locked) {
-                            connection.expire(getWriteKey(), 30);
+                            connection.expire(getWriteKey(), lockKeyExpireTime);
                             return true;
                         }
                     }
@@ -209,7 +244,7 @@ public class RedisReadWriteLock implements ReadWriteLock {
 
         @Override
         public Condition newCondition() {
-            return null;
+            throw new UnsupportedOperationException();
         }
     }
 }