[Feature] add for new
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
package com.github.houbb.lock.api.core;
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读写锁定义
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 0.0.2
|
||||||
|
*/
|
||||||
|
public interface IReadWriteLock extends ReadWriteLock {
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.github.houbb.lock.redis.core;
|
|||||||
import com.github.houbb.lock.api.core.ILock;
|
import com.github.houbb.lock.api.core.ILock;
|
||||||
import com.github.houbb.lock.redis.constant.LockRedisConst;
|
import com.github.houbb.lock.redis.constant.LockRedisConst;
|
||||||
import com.github.houbb.wait.api.IWait;
|
import com.github.houbb.wait.api.IWait;
|
||||||
|
import com.github.houbb.wait.core.Waits;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.locks.Condition;
|
||||||
@@ -12,7 +13,7 @@ import java.util.concurrent.locks.Condition;
|
|||||||
* @author binbin.hou
|
* @author binbin.hou
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractLockRedis implements ILock {
|
public abstract class AbstractLock implements ILock {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 锁等待
|
* 锁等待
|
||||||
@@ -20,7 +21,11 @@ public abstract class AbstractLockRedis implements ILock {
|
|||||||
*/
|
*/
|
||||||
private final IWait wait;
|
private final IWait wait;
|
||||||
|
|
||||||
protected AbstractLockRedis(IWait wait) {
|
public AbstractLock() {
|
||||||
|
this.wait = Waits.threadSleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractLock(IWait wait) {
|
||||||
this.wait = wait;
|
this.wait = wait;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,8 +73,8 @@ public abstract class AbstractLockRedis implements ILock {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待 10ms
|
// 等待 1ms
|
||||||
wait.wait(TimeUnit.MILLISECONDS, 10);
|
wait.wait(TimeUnit.MILLISECONDS, 1);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ import com.github.houbb.wait.api.IWait;
|
|||||||
* @author binbin.hou
|
* @author binbin.hou
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
public class LockRedis extends AbstractLockRedis {
|
public class LockRedis extends AbstractLock {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* redis 操作实现
|
* redis 操作实现
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.github.houbb.lock.redis.core;
|
||||||
|
|
||||||
|
import com.github.houbb.lock.redis.exception.LockRuntimeException;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自旋锁
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 0.0.2
|
||||||
|
*/
|
||||||
|
public class LockSpin extends AbstractLock {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* volatile 引用,保证线程间的可见性+易变性
|
||||||
|
*
|
||||||
|
* @since 0.0.2
|
||||||
|
*/
|
||||||
|
private AtomicReference<Thread> owner =new AtomicReference<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lock() {
|
||||||
|
// 循环等待,直到获取到锁
|
||||||
|
while (!tryLock()) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryLock(String key) {
|
||||||
|
Thread current = Thread.currentThread();
|
||||||
|
// CAS
|
||||||
|
return owner.compareAndSet(null, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unlock(String key) {
|
||||||
|
Thread current = Thread.currentThread();
|
||||||
|
boolean result = owner.compareAndSet(current, null);
|
||||||
|
if(!result) {
|
||||||
|
throw new LockRuntimeException("解锁失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.github.houbb.lock.redis.core;
|
||||||
|
|
||||||
|
import com.github.houbb.heaven.util.util.DateUtil;
|
||||||
|
import com.github.houbb.lock.redis.exception.LockRuntimeException;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自旋锁-可重入
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 0.0.2
|
||||||
|
*/
|
||||||
|
public class LockSpinRe extends AbstractLock {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* volatile 引用,保证线程间的可见性+易变性
|
||||||
|
*
|
||||||
|
* @since 0.0.2
|
||||||
|
*/
|
||||||
|
private AtomicReference<Thread> owner =new AtomicReference<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计数统计类
|
||||||
|
*
|
||||||
|
* @since 0.0.2
|
||||||
|
*/
|
||||||
|
private AtomicLong count = new AtomicLong(0);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lock() {
|
||||||
|
// 循环等待,直到获取到锁
|
||||||
|
while (!tryLock()) {
|
||||||
|
// sleep
|
||||||
|
DateUtil.sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryLock(String key) {
|
||||||
|
Thread current = Thread.currentThread();
|
||||||
|
// 判断是否已经拥有此锁
|
||||||
|
if(current == owner.get()) {
|
||||||
|
// 原子性自增 1
|
||||||
|
count.incrementAndGet();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CAS
|
||||||
|
return owner.compareAndSet(null, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unlock(String key) {
|
||||||
|
Thread current = Thread.currentThread();
|
||||||
|
|
||||||
|
// 可重入实现
|
||||||
|
if(owner.get() == current && count.get() != 0) {
|
||||||
|
count.decrementAndGet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean result = owner.compareAndSet(current, null);
|
||||||
|
if(!result) {
|
||||||
|
throw new LockRuntimeException("解锁失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.github.houbb.lock.redis.core;
|
||||||
|
|
||||||
|
import com.github.houbb.lock.redis.exception.LockRuntimeException;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 等待通知的锁实现
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 0.0.2
|
||||||
|
*/
|
||||||
|
public class LockWaitNotify extends AbstractLock {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* volatile 引用,保证线程间的可见性+易变性
|
||||||
|
*
|
||||||
|
* @since 0.0.2
|
||||||
|
*/
|
||||||
|
private AtomicReference<Thread> owner =new AtomicReference<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void lock() {
|
||||||
|
while (!tryLock()) {
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
// 是否可以被打断
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryLock(String key) {
|
||||||
|
Thread current = Thread.currentThread();
|
||||||
|
// CAS
|
||||||
|
return owner.compareAndSet(null, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void unlock(String key) {
|
||||||
|
Thread current = Thread.currentThread();
|
||||||
|
boolean result = owner.compareAndSet(current, null);
|
||||||
|
if(!result) {
|
||||||
|
throw new LockRuntimeException("解锁失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 唤醒等待中的线程
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.github.houbb.lock.redis.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 0.0.2
|
||||||
|
*/
|
||||||
|
public class LockRuntimeException extends RuntimeException {
|
||||||
|
|
||||||
|
public LockRuntimeException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRuntimeException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRuntimeException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRuntimeException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||||
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.github.houbb.lock.test.core;
|
||||||
|
|
||||||
|
import com.github.houbb.lock.api.core.ILock;
|
||||||
|
import com.github.houbb.lock.redis.core.LockSpin;
|
||||||
|
import com.github.houbb.lock.redis.core.LockSpinRe;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public class LockSpinReThread implements Runnable {
|
||||||
|
|
||||||
|
private final ILock lock = new LockSpinRe();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
System.out.println("first-lock: " + Thread.currentThread().getId());
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
System.out.println("second-lock: " + Thread.currentThread().getId());
|
||||||
|
lock.lock();
|
||||||
|
lock.unlock();
|
||||||
|
System.out.println("second-unlock: " + Thread.currentThread().getId());
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
System.out.println("first-unlock: " + Thread.currentThread().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final Runnable runnable = new LockSpinReThread();
|
||||||
|
new Thread(runnable).start();
|
||||||
|
new Thread(runnable).start();
|
||||||
|
new Thread(runnable).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.github.houbb.lock.test.core;
|
||||||
|
|
||||||
|
import com.github.houbb.lock.api.core.ILock;
|
||||||
|
import com.github.houbb.lock.redis.core.LockSpin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public class LockSpinThread implements Runnable {
|
||||||
|
|
||||||
|
private final ILock lock = new LockSpin();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
System.out.println("first-lock: " + Thread.currentThread().getId());
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
System.out.println("second-lock: " + Thread.currentThread().getId());
|
||||||
|
lock.lock();
|
||||||
|
lock.unlock();
|
||||||
|
System.out.println("second-unlock: " + Thread.currentThread().getId());
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
System.out.println("first-unlock: " + Thread.currentThread().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final Runnable runnable = new LockSpinThread();
|
||||||
|
new Thread(runnable).start();
|
||||||
|
new Thread(runnable).start();
|
||||||
|
new Thread(runnable).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.github.houbb.lock.test.core;
|
||||||
|
|
||||||
|
import com.github.houbb.lock.api.core.ILock;
|
||||||
|
import com.github.houbb.lock.redis.core.LockWaitNotify;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public class LockWaitNotifyThread implements Runnable {
|
||||||
|
|
||||||
|
private final ILock lock = new LockWaitNotify();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
System.out.println("first-lock: " + Thread.currentThread().getId());
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
// System.out.println("second-lock: " + Thread.currentThread().getId());
|
||||||
|
// lock.lock();
|
||||||
|
// lock.unlock();
|
||||||
|
// System.out.println("second-unlock: " + Thread.currentThread().getId());
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
TimeUnit.SECONDS.sleep(5);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
lock.unlock();
|
||||||
|
System.out.println("first-unlock: " + Thread.currentThread().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final Runnable runnable = new LockWaitNotifyThread();
|
||||||
|
new Thread(runnable).start();
|
||||||
|
new Thread(runnable).start();
|
||||||
|
new Thread(runnable).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import redis.clients.jedis.Jedis;
|
|||||||
* @author binbin.hou
|
* @author binbin.hou
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
public class RedisLockTest {
|
public class LockRedisTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void helloTest() {
|
public void helloTest() {
|
||||||
Reference in New Issue
Block a user