[Feature] add for new

This commit is contained in:
binbin.hou
2020-10-19 18:23:20 +08:00
parent acbd8f4022
commit 67f8b1e2a7
11 changed files with 329 additions and 6 deletions

View File

@@ -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 {
}

View File

@@ -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;
} }

View File

@@ -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 操作实现

View File

@@ -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("解锁失败");
}
}
}

View File

@@ -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("解锁失败");
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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() {