Skip to content

Commit

Permalink
version 0.9.0.0 update
Browse files Browse the repository at this point in the history
完善读写锁注解,现在可以使用自定义的读写锁
  • Loading branch information
ZongXR committed Feb 4, 2022
1 parent 458f1d9 commit 34d225d
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 72 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,7 @@
<tr>
<td>0.8.1.0</td><td>完善写锁,提供最长等待时间,最长执行时间,是否强制执行等属性,全方位避免死锁</td><td>2022年2月4日</td>
</tr>
<tr>
<td>0.9.0.0</td><td>完善读写锁注解,现在可以使用自定义的读写锁</td><td>2022年2月4日</td>
</tr>
</table>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@
public @interface ReadLock {

/**
* 是否公平锁
* 读写锁变量的名称,该变量必须是{@code ReentrantReadWriteLock}类的对象或其子类对象
* @return 默认使用编译生成的
*/
String value() default "";

/**
* 编译时生成的是否公平锁,该属性仅在{@code value}属性保持默认时才生效
* @return 默认null,如果有自定义值则覆盖默认值
*/
BooleanEnum fair() default NULL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@
public @interface WriteLock {

/**
* 是否公平锁
* 读写锁变量的名称,该变量必须是{@code ReentrantReadWriteLock}类的对象或其子类对象
* @return 默认使用编译生成的
*/
String value() default "";

/**
* 编译时生成的是否公平锁,该属性仅在{@code value}属性保持默认时才生效
* @return 默认null,如果有自定义值则覆盖默认值
*/
BooleanEnum fair() default NULL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
* 每个注解上都有对应的注释,写得很清楚,自己看就可以了,不加以赘述.
* 需要注意的是,如果需要使锁注解生效,需要在springboot启动类上添加{@code @EnableSpringLocks}注解
* @author 宗祥瑞
* @version 0.8.1.0
* @version 0.9.0.0
*/
package org.springframework.lock.annotation;
70 changes: 37 additions & 33 deletions src/main/java/org/springframework/lock/aspect/ReadLockAspect.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.lock.annotation.ReadLock;
import org.springframework.lock.timer.InterruptTimer;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -35,49 +36,52 @@ public class ReadLockAspect {
*/
@Around("@annotation(org.springframework.lock.annotation.ReadLock)")
public Object aroundReadLock(ProceedingJoinPoint jp) throws Throwable {
Object obj = jp.getTarget();
Class<?> clz = obj.getClass();
Lock readLock = null;
ReentrantReadWriteLock lock = null;
for (Field field : clz.getDeclaredFields()) {
if ("$readLock".equals(field.getName())){
field.setAccessible(true);
readLock = (Lock) field.get(obj);
}
if ("$lock".equals(field.getName())){
field.setAccessible(true);
lock = (ReentrantReadWriteLock) field.get(obj);
}
if (lock != null && readLock != null)
// 都找到了
break;
}
if (readLock == null || lock == null){
// 连锁都没拿到,说明编译期间出了问题
LOGGER.warn(clz.getSimpleName() + "编译时生成读写锁锁失败,未能加锁");
return jp.proceed();
}

// 获取注解的属性
long waitTime = Long.MAX_VALUE;
long executeTime = Long.MAX_VALUE;
boolean isContinueIfElapsed = false;
boolean withLockIfContinue = false;
String lockName = null;

MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod();
if (method == null) {
// 没拿到方法,那注解给了谁呢?
LOGGER.warn("没拿到方法" + signature);
return jp.proceed();
}
ReadLock annotation = method.getAnnotation(ReadLock.class);
if (annotation != null) {
waitTime = annotation.waitTime();
executeTime = annotation.executeTime();
isContinueIfElapsed = annotation.isContinueIfElapsed();
withLockIfContinue = annotation.withLockIfContinue();
lockName = annotation.value();
}

// 获取锁对象
Lock readLock = null;
ReentrantReadWriteLock lock = null;
Object obj = jp.getTarget();
Class<?> clz = obj.getClass();
Field field = null;

if (StringUtils.hasText(lockName)){
field = clz.getDeclaredField(lockName);
field.setAccessible(true);
lock = (ReentrantReadWriteLock) field.get(obj);
readLock = lock.readLock();
}else {
field = clz.getDeclaredField("$readLock");
field.setAccessible(true);
readLock = (Lock) field.get(obj);
field = clz.getDeclaredField("$lock");
field.setAccessible(true);
lock = (ReentrantReadWriteLock) field.get(obj);
}

if (readLock == null || lock == null){
// 连锁都没拿到,说明编译期间出了问题
LOGGER.warn(clz.getSimpleName() + "获取锁错误,请检查锁名称是否正确");
return jp.proceed();
}

// 尝试加锁,不行就结束掉别人的线程
Object result = null;
boolean locked = readLock.tryLock(waitTime, MILLISECONDS);
if (locked) {
Expand All @@ -91,12 +95,12 @@ public Object aroundReadLock(ProceedingJoinPoint jp) throws Throwable {
Thread lockedThread = (Thread) getOwner.invoke(lock);
lockedThread.interrupt();
if (readLock.tryLock(waitTime, MILLISECONDS)){
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得锁");
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得读锁" + readLock);
result = this.processMethod(jp, readLock, executeTime);
}else{
lockedThread.stop();
if (readLock.tryLock(waitTime, MILLISECONDS)){
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得锁");
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得读锁" + readLock);
result = this.processMethod(jp, readLock, executeTime);
}
}
Expand All @@ -105,7 +109,7 @@ public Object aroundReadLock(ProceedingJoinPoint jp) throws Throwable {
result = jp.proceed();
}
}else {
LOGGER.warn("等待时间耗尽,将不执行" + method.getName());
LOGGER.warn("等待时间耗尽,放弃执行" + method.getName());
}
}
return result;
Expand All @@ -121,13 +125,13 @@ public Object aroundReadLock(ProceedingJoinPoint jp) throws Throwable {
*/
private Object processMethod(ProceedingJoinPoint jp, Lock readLock, long executeTime) throws Throwable {
Object result = null;
LOGGER.info(Thread.currentThread().getName() + "获得读锁");
LOGGER.info(Thread.currentThread().getName() + "获得读锁" + readLock);
new InterruptTimer(Thread.currentThread(), executeTime);
try {
result = jp.proceed();
} finally {
readLock.unlock();
LOGGER.info(Thread.currentThread().getName() + "释放读锁");
LOGGER.info(Thread.currentThread().getName() + "释放读锁" + readLock);
}
return result;
}
Expand Down
68 changes: 36 additions & 32 deletions src/main/java/org/springframework/lock/aspect/WriteLockAspect.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.lock.annotation.WriteLock;
import org.springframework.lock.timer.InterruptTimer;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -35,49 +36,52 @@ public class WriteLockAspect {
*/
@Around("@annotation(org.springframework.lock.annotation.WriteLock)")
public Object aroundWriteLock(ProceedingJoinPoint jp) throws Throwable {
Object obj = jp.getTarget();
Class<?> clz = obj.getClass();
Lock writeLock = null;
ReentrantReadWriteLock lock = null;
for (Field field : clz.getDeclaredFields()) {
if ("$writeLock".equals(field.getName())){
field.setAccessible(true);
writeLock = (Lock) field.get(obj);
}
if ("$lock".equals(field.getName())){
field.setAccessible(true);
lock = (ReentrantReadWriteLock) field.get(obj);
}
if (lock != null && writeLock != null)
// 都找到了
break;
}
if (lock == null || writeLock == null){
// 连锁都没拿到,说明编译期间出了问题
LOGGER.warn(clz.getSimpleName() + "编译时生成读写锁锁失败,未能加锁");
return jp.proceed();
}

// 获取注解的属性
long waitTime = Long.MAX_VALUE;
long executeTime = Long.MAX_VALUE;
boolean isContinueIfElapsed = false;
boolean withLockIfContinue = false;
String lockName = null;

MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod();
if (method == null) {
// 没拿到方法,那注解给了谁呢?
LOGGER.warn("没拿到方法" + signature);
return jp.proceed();
}
WriteLock annotation = method.getAnnotation(WriteLock.class);
if (annotation != null) {
waitTime = annotation.waitTime();
executeTime = annotation.executeTime();
isContinueIfElapsed = annotation.isContinueIfElapsed();
withLockIfContinue = annotation.withLockIfContinue();
lockName = annotation.value();
}

// 获取锁对象
Lock writeLock = null;
ReentrantReadWriteLock lock = null;
Object obj = jp.getTarget();
Class<?> clz = obj.getClass();
Field field = null;

if (StringUtils.hasText(lockName)){
field = clz.getDeclaredField(lockName);
field.setAccessible(true);
lock = (ReentrantReadWriteLock) field.get(obj);
writeLock = lock.writeLock();
}else {
field = clz.getDeclaredField("$writeLock");
field.setAccessible(true);
writeLock = (Lock) field.get(obj);
field = clz.getDeclaredField("$lock");
field.setAccessible(true);
lock = (ReentrantReadWriteLock) field.get(obj);
}

if (lock == null || writeLock == null){
// 连锁都没拿到,说明编译期间出了问题
LOGGER.warn(clz.getSimpleName() + "编译时生成读写锁锁失败,未能加锁");
return jp.proceed();
}

// 尝试加锁,不行就结束掉别人的线程
Object result = null;
boolean locked = writeLock.tryLock(waitTime, MILLISECONDS);
if (locked) {
Expand All @@ -91,12 +95,12 @@ public Object aroundWriteLock(ProceedingJoinPoint jp) throws Throwable {
Thread lockedThread = (Thread) getOwner.invoke(lock);
lockedThread.interrupt();
if (writeLock.tryLock(waitTime, MILLISECONDS)){
LOGGER.warn("等待时间耗尽,中断线程" + lockedThread + "以强制获得锁");
LOGGER.warn("等待时间耗尽,中断线程" + lockedThread + "以强制获得写锁" + writeLock);
result = this.processMethod(jp, writeLock, executeTime);
}else {
lockedThread.stop();
if (writeLock.tryLock(waitTime, MILLISECONDS)) {
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得锁");
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得写锁" + writeLock);
result = this.processMethod(jp, writeLock, executeTime);
}
}
Expand All @@ -122,13 +126,13 @@ public Object aroundWriteLock(ProceedingJoinPoint jp) throws Throwable {
*/
private Object processMethod(ProceedingJoinPoint jp, Lock writeLock, long executeTime) throws Throwable {
Object result = null;
LOGGER.info(Thread.currentThread().getName() + "获得写锁");
LOGGER.info(Thread.currentThread().getName() + "获得写锁" + writeLock);
new InterruptTimer(Thread.currentThread(), executeTime);
try {
result = jp.proceed();
} finally {
writeLock.unlock();
LOGGER.info(Thread.currentThread().getName() + "释放写锁");
LOGGER.info(Thread.currentThread().getName() + "释放写锁" + writeLock);
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
* 每个切面都有注释,没什么好说的,不加以赘述.
* 切面这部分需要托管到spring容器中去执行.
* @author 宗祥瑞
* @version 0.8.1.0
* @version 0.9.0.0
*/
package org.springframework.lock.aspect;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* 这是关于枚举类型的包.
* 写得很清楚,直接看代码就好了.
* @version 0.8.1.0
* @version 0.9.0.0
* @author 宗祥瑞
*/
package org.springframework.lock.enumeration;
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
* 它的原理与lombok有些许类似,但代码风格比lombok更好理解,一看就懂
* 每个处理器都写了注释,写得都很清楚,不加以赘述
* @author 宗祥瑞
* @version 0.8.1.0
* @version 0.9.0.0
*/
package org.springframework.lock.processor;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
* 意思就是在多长时间后执行什么功能,或者要求每过多长时间执行什么功能.
* java不能多继承,所以用内部类来实现
* @author 宗祥瑞
* @version 0.8.1.0
* @version 0.9.0.0
*/
package org.springframework.lock.timer;

0 comments on commit 34d225d

Please sign in to comment.