diff --git a/README.md b/README.md index f387e90b49704a1bf91a014b7436a5233923cb1f..6b083dc3c13251d6f241add2131731d95a0ec15d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -

Icon # PDConcurrent @@ -33,7 +32,7 @@ public static void main(String[] args) { lock.read(() -> { // 并发域代码内容 - [return null;]? // 可选择是否返回 + return null; // 可选择是否返回 }); } ``` @@ -56,11 +55,13 @@ void main(String[] args) { // 使用 lock.read(() -> { // 并发域代码内容 + return null; }); // 不使用 - synchronized ( new Object() ){ + synchronized ( lock ){ // 并发域代码内容 + return null; } } @@ -70,8 +71,6 @@ void main(String[] args) { 支持使用`newCondition()`获取`Condition`对象 -支持通过`isLocked()`检查是否被占用 - ```java public static void main(String[] args) { diff --git a/build.gradle b/build.gradle index bceb43517581372e06266cf332d095e190041647..7b260779b34aa9e5c95eed842ffaddfb4b20705d 100644 --- a/build.gradle +++ b/build.gradle @@ -53,12 +53,12 @@ dependencies { // lombok testCompileOnly "org.projectlombok:lombok:+" testAnnotationProcessor "org.projectlombok:lombok:+" - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + testRuntimeOnly "org.junit.jupiter:junit-jupiter:5.12.0+" } test { dependencies { - testImplementation "org.junit.platform:junit-platform-launcher" + testImplementation "org.junit.jupiter:junit-jupiter:5.12.0+" } useJUnitPlatform() } @@ -83,7 +83,7 @@ tasks.withType(Jar).configureEach { /** 编译包 */ tasks.register('PDConcurrent_bin', Jar) { archiveFileName = 'PDConcurrent_bin.jar' - archiveClassifier = '' + archiveClassifier = 'bin' // 打包编译输出 from sourceSets.main.output } @@ -96,17 +96,6 @@ tasks.register('PDConcurrent_sources', Jar) { from sourceSets.main.allSource } -//tasks.register('PDConcurrent_all', Jar) { -// archiveFileName = 'PDConcurrent_all.jar' -// archiveClassifier = 'all' -// // 打包编译输出 -// from sourceSets.main.output -// from { -// // implementation 相关的引入解压并打包入新的jar中 -// configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } -// } -//} - tasks.register('release') { dependsOn PDConcurrent_bin dependsOn PDConcurrent_sources diff --git a/jar/PDConcurrent_bin.jar b/jar/PDConcurrent_bin.jar index b8cac15ec28adeb50b1b857d8b05d8a9bfd79d90..7c201907b4d9571e7718389e537db8c357499f93 100644 Binary files a/jar/PDConcurrent_bin.jar and b/jar/PDConcurrent_bin.jar differ diff --git a/jar/PDConcurrent_sources.jar b/jar/PDConcurrent_sources.jar index faaffcee6bc8121a4c9264a801a03ab9485cee1a..e3154d1e5af5524fde7b237cd5877ad67a2b35db 100644 Binary files a/jar/PDConcurrent_sources.jar and b/jar/PDConcurrent_sources.jar differ diff --git a/src/main/java/fybug/nulll/pdconcurrent/SyLock.java b/src/main/java/fybug/nulll/pdconcurrent/SyLock.java index 113455068eec4dc9ff6655b39c62ab13b0fd9a87..32216c4a5694b1b97644d6b13d836884c9aa3d05 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/SyLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/SyLock.java @@ -1,528 +1,28 @@ package fybug.nulll.pdconcurrent; -import java.util.function.Consumer; -import java.util.function.Function; - import fybug.nulll.pdconcurrent.e.LockType; -import fybug.nulll.pdconcurrent.fun.tryRunnable; -import fybug.nulll.pdconcurrent.fun.trySupplier; -import jakarta.annotation.Nullable; +import fybug.nulll.pdconcurrent.i.ReadWriteLock; +import fybug.nulll.pdconcurrent.i.TryReadWriteLock; +import fybug.nulll.pdconcurrent.lock.ObjLock; +import fybug.nulll.pdconcurrent.lock.RWLock; +import fybug.nulll.pdconcurrent.lock.ReLock; import jakarta.validation.constraints.NotNull; /** *

并发管理.

* 通过传入回调的方式隐藏内部的并发管理方法,并支持复用内部的try块,通过传入的回调插入到catch,finally块中执行
- * {@code **lock()} 方法用于根据传入的{@link LockType}申请不同的锁类型进行执行
- * {@code **read()} 方法用于申请使用读锁,{@code **write()} 用于申请使用写锁,只有在使用读写锁实现 {@link RWLock} 才有区别。其余实现两个之间无区别
- * {@code try**()} 类型的方法为可抛出异常的方法,可在传入的接口中抛出异常 + * {@code lock()}方法用于根据传入的{@link LockType}申请不同的锁类型进行执行
+ * {@code read()}方法用于使用读锁执行,{@code write()}用于使用写锁执行,只有在使用读写锁实现{@link RWLock}才有区别。其余实现两个之间无区别
+ * {@code trylock()}类型的方法为尝试获取锁的实现,这意味着并不是一定能获取到锁,但也意味着不需要等待
+ * 上述方法均有可抛出异常的变种 *

* 使用 {@code new**Lock()} 的方法获取不同并发管理的实例
* * @author fybug - * @version 0.1.1 + * @version 0.1.2 * @since PDConcurrent 0.0.1 */ public -interface SyLock { - /** - * 使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param lockType 锁类型 - * @param run 带返回的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调,传入前两个回调的返回值 - * @param 要返回的数据类型 - * - * @return 回调返回的内容 - * - * @implSpec 如果有传入 {@code finaby} 回调则返回值由{@code finaby}主导,传入{@code finaby}的值根据是否发生异常传入{@code run}的返回值或{@code catchby}的返回值
- * 任意一个回调为空时直接穿透,使用上一个正确执行的值进行传递或者返回,传递值应默认为{@code null}用于应对{@code catchby}和{@code finaby}都为空但是发生了异常的情况 - * @see trySupplier - * @see Function - * @see LockType - * @since 0.1.0 - */ - R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function catchby, - @Nullable Function finaby); - - /** - * 使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param lockType 锁类型 - * @param run 执行的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调 - * - * @see tryRunnable - * @see Consumer - * @see Runnable - * @see LockType - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - void lock(@NotNull LockType lockType, @NotNull tryRunnable run, @Nullable Consumer catchby, - @Nullable Runnable finaby) - { - lock(lockType, () -> { - run.run(); - return null; - }, catchby == null ? null : e -> { - catchby.accept(e); - return null; - }, finaby == null ? null : _ -> { - finaby.run(); - return null; - }); - } - - /** - * 使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,遇到异常不处理返回{@code null} - * - * @param lockType 锁类型 - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常返回{@code null} - * - * @see trySupplier - * @see LockType - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - R lock(@NotNull LockType lockType, @NotNull trySupplier run) - { return lock(lockType, run, null, null); } - - /** - * 使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,遇到异常不处理 - * - * @param lockType 锁类型 - * @param run 执行的回调 - * - * @see tryRunnable - * @see LockType - * @see #lock(LockType, tryRunnable, Consumer, Runnable) - * @since 0.1.0 - */ - default - void lock(@NotNull LockType lockType, @NotNull tryRunnable run) - { lock(lockType, run, null, null); } - - /** - * 尝试使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
- * 所有回调均在并发域内执行 - * - * @param lockType 锁类型 - * @param run 带返回的回调 - * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常不返回 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @implSpec 如果有传入 {@code finaby} 回调则返回值由{@code finaby}主导,传入{@code finaby}的值根据是否发生异常传入{@code run}的返回值或{@code null}
- * 任意一个回调为空时直接穿透,使用上一个正确执行的值进行传递或者返回,发生异常会执行{@code finaby}但是不会返回内容 - * @see trySupplier - * @see Function - * @see LockType - * @since 0.1.0 - */ - R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception; - - /** - * 尝试使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
- * 所有回调均在并发域内执行 - * - * @param lockType 锁类型 - * @param run 执行的回调 - * @param finaby 进入finally块后的回调 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see tryRunnable - * @see Runnable - * @see LockType - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - void trylock(@NotNull LockType lockType, @NotNull tryRunnable run, @Nullable Runnable finaby) throws Exception { - trylock(lockType, () -> { - run.run(); - return null; - }, finaby == null ? null : _ -> { - finaby.run(); - return null; - }); - } - - /** - * 尝试使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,遇到异常会抛出 - * - * @param lockType 锁类型 - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常不返回 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see trySupplier - * @see LockType - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - R trylock(@NotNull LockType lockType, @NotNull trySupplier run) throws Exception - { return trylock(lockType, run, null); } - - /** - * 尝试使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,遇到异常会抛出 - * - * @param lockType 锁类型 - * @param run 执行的回调 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see tryRunnable - * @see LockType - * @see #trylock(LockType, tryRunnable, Runnable) - * @since 0.1.0 - */ - default - void trylock(@NotNull LockType lockType, @NotNull tryRunnable run) throws Exception - { trylock(lockType, run, null); } - - /** - * 使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-catch-finally块,遇到异常不处理 - * - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容 - * - * @see trySupplier - * @see LockType#READ - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - R read(@NotNull trySupplier run) - { return lock(LockType.READ, run, null, null); } - - /** - * 使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-catch-finally块,遇到异常不处理 - * - * @param run 执行的回调 - * - * @see tryRunnable - * @see LockType#READ - * @see #lock(LockType, tryRunnable, Consumer, Runnable) - * @since 0.1.0 - */ - default - void read(@NotNull tryRunnable run) - { lock(LockType.READ, run, null, null); } - - /** - * 使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-catch-finally块,遇到异常不处理 - * - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容 - * - * @see trySupplier - * @see LockType#WRITE - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - R write(@NotNull trySupplier run) - { return lock(LockType.WRITE, run, null, null); } - - /** - * 使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-catch-finally块,遇到异常不处理 - * - * @param run 执行的回调 - * - * @see tryRunnable - * @see LockType#WRITE - * @see #lock(LockType, tryRunnable, Consumer, Runnable) - * @since 0.1.0 - */ - default - void write(@NotNull tryRunnable run) - { lock(LockType.WRITE, run, null, null); } - - /** - * 使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param run 带返回的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调,传入前两个回调的返回值 - * @param 要返回的数据类型 - * - * @return 回调返回的内容 - * - * @see trySupplier - * @see Function - * @see LockType#READ - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - R read(@NotNull trySupplier run, @Nullable Function catchby, @Nullable Function finaby) - { return lock(LockType.READ, run, catchby, finaby); } - - /** - * 使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param run 执行的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调 - * - * @see tryRunnable - * @see Consumer - * @see Runnable - * @see LockType#READ - * @see #lock(LockType, tryRunnable, Consumer, Runnable) - * @since 0.1.0 - */ - default - void read(@NotNull tryRunnable run, @Nullable Consumer catchby, @Nullable Runnable finaby) - { lock(LockType.READ, run, catchby, finaby); } - - /** - * 使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param run 带返回的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调,传入前两个回调的返回值 - * @param 要返回的数据类型 - * - * @return 回调返回的内容 - * - * @see trySupplier - * @see Function - * @see LockType#WRITE - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - R write(@NotNull trySupplier run, @Nullable Function catchby, @Nullable Function finaby) - { return lock(LockType.WRITE, run, catchby, finaby); } - - /** - * 使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param run 执行的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调 - * - * @see tryRunnable - * @see Consumer - * @see Runnable - * @see LockType#WRITE - * @see #lock(LockType, tryRunnable, Consumer, Runnable) - * @since 0.1.0 - */ - default - void write(@NotNull tryRunnable run, @Nullable Consumer catchby, @Nullable Runnable finaby) - { lock(LockType.WRITE, run, catchby, finaby); } - - /** - * 尝试使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-finally块,遇到异常会抛出 - * - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常不返回 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see trySupplier - * @see LockType#READ - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - R tryread(@NotNull trySupplier run) throws Exception - { return trylock(LockType.READ, run, null); } - - /** - * 尝试使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-finally块,遇到异常会抛出 - * - * @param run 执行的回调 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see tryRunnable - * @see LockType#READ - * @see #trylock(LockType, tryRunnable, Runnable) - * @since 0.1.0 - */ - default - void tryread(@NotNull tryRunnable run) throws Exception - { trylock(LockType.READ, run, null); } - - /** - * 尝试使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-finally块,遇到异常会抛出 - * - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常不返回 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see trySupplier - * @see LockType#WRITE - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - R trywrite(@NotNull trySupplier run) throws Exception - { return trylock(LockType.WRITE, run, null); } - - /** - * 尝试使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-finally块,遇到异常会抛出 - * - * @param run 执行的回调 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see tryRunnable - * @see LockType#WRITE - * @see #trylock(LockType, tryRunnable, Runnable) - * @since 0.1.0 - */ - default - void trywrite(@NotNull tryRunnable run) throws Exception - { trylock(LockType.WRITE, run, null); } - - /** - * 尝试使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
- * 所有回调均在并发域内执行 - * - * @param run 带返回的回调 - * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常不返回 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see trySupplier - * @see LockType#READ - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - R tryread(@NotNull trySupplier run, @Nullable Function finaby) throws Exception - { return trylock(LockType.READ, run, finaby); } - - /** - * 尝试使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
- * 所有回调均在并发域内执行 - * - * @param run 执行的回调 - * @param finaby 进入finally块后的回调 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see trySupplier - * @see LockType#READ - * @see #trylock(LockType, tryRunnable, Runnable) - * @since 0.1.1 - */ - default - void tryread(@NotNull tryRunnable run, @Nullable Runnable finaby) throws Exception - { trylock(LockType.READ, run, finaby); } - - /** - * 尝试使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
- * 所有回调均在并发域内执行 - * - * @param run 带返回的回调 - * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常不返回 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see trySupplier - * @see LockType#WRITE - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.1 - */ - default - R trywrite(@NotNull trySupplier run, @Nullable Function finaby) throws Exception - { return trylock(LockType.WRITE, run, finaby); } - - /** - * 尝试使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
- * 所有回调均在并发域内执行 - * - * @param run 执行的回调 - * @param finaby 进入finally块后的回调 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see trySupplier - * @see LockType#WRITE - * @see #trylock(LockType, tryRunnable, Runnable) - * @since 0.1.1 - */ - default - void trywrite(@NotNull tryRunnable run, @Nullable Runnable finaby) throws Exception - { trylock(LockType.WRITE, run, finaby); } - +interface SyLock extends ReadWriteLock, TryReadWriteLock { /** * 获取传统并发实现 * @@ -530,6 +30,7 @@ interface SyLock { * * @see ObjLock */ + @SuppressWarnings("unused") @NotNull static ObjLock newObjLock() { return new ObjLock(); } @@ -541,6 +42,7 @@ interface SyLock { * * @see ReLock */ + @SuppressWarnings("unused") @NotNull static ReLock newReLock() { return new ReLock(); } @@ -552,6 +54,7 @@ interface SyLock { * * @see RWLock */ + @SuppressWarnings("unused") @NotNull static RWLock newRWLock() { return new RWLock(); } diff --git a/src/main/java/fybug/nulll/pdconcurrent/e/LockType.java b/src/main/java/fybug/nulll/pdconcurrent/e/LockType.java index 0562106c5445f0c453580b1a11a0b88c7e0d834c..0df827d0f75a46a4fc56faa2bb8ec54dcc060890 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/e/LockType.java +++ b/src/main/java/fybug/nulll/pdconcurrent/e/LockType.java @@ -5,7 +5,7 @@ package fybug.nulll.pdconcurrent.e; * * @author fybug * @version 0.0.1 - * @since PDConcurrent 0.1.0 + * @since e 0.0.1 */ public enum LockType { @@ -13,6 +13,10 @@ enum LockType { READ, /** 写锁 */ WRITE, - /** 不上锁 */ + /** + * 不上锁 + *

+ * 该方式要求这次锁行为不会被记录与执行,故解锁时本次行为会被跳过转而解锁上一次的锁 + */ NOLOCK } diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java b/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java index b1a3114481f9779f345170caacf7d816a17f2eaf..c9dde4d5d9088c0913a78f106731895f57623f07 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java @@ -12,6 +12,8 @@ import jakarta.validation.constraints.NotNull; * @see Consumer * @since fun 0.0.4 */ +@SuppressWarnings("unused") +@FunctionalInterface public interface tryConsumer { /** @see Consumer#accept(Object) */ diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/tryFunction.java b/src/main/java/fybug/nulll/pdconcurrent/fun/tryFunction.java index d3fa122e489991034d55560ae3175c1ec31c9fcf..af64f16749793a3d890b0c0adee374954e622c2f 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/tryFunction.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/tryFunction.java @@ -13,6 +13,8 @@ import jakarta.validation.constraints.NotNull; * @see Function * @since fun 0.0.4 */ +@SuppressWarnings("unused") +@FunctionalInterface public interface tryFunction { /** @see Function#apply(Object) */ @@ -33,6 +35,7 @@ interface tryFunction { tryFunction andThen(@Nullable tryFunction after) { if ( after != null ) return t -> after.apply(apply(t)); + //noinspection unchecked return (tryFunction) this; } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/tryRunnable.java b/src/main/java/fybug/nulll/pdconcurrent/fun/tryRunnable.java index 99be4362ec66add63659e87796c830002afdffbb..67330671aa2a4bf9ec54920f1d3342c08a876f69 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/tryRunnable.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/tryRunnable.java @@ -8,6 +8,7 @@ import jakarta.validation.constraints.NotNull; * @see Runnable * @since fun 0.0.4 */ +@SuppressWarnings("unused") @FunctionalInterface public interface tryRunnable { diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/trySupplier.java b/src/main/java/fybug/nulll/pdconcurrent/fun/trySupplier.java index 5acbc79550cc20962d9377a7388708cd92b1a71f..d59a835951cc9d0501d0fee065c42b8816c4b8be 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/trySupplier.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/trySupplier.java @@ -12,6 +12,7 @@ import jakarta.validation.constraints.NotNull; * @see Supplier * @since fun 0.0.4 */ +@SuppressWarnings("unused") @FunctionalInterface public interface trySupplier { @@ -19,6 +20,7 @@ interface trySupplier { R get() throws Exception; /** @since 0.0.2 */ + @SuppressWarnings("unused") @NotNull default tryRunnable andThen(@Nullable tryConsumer after) { @@ -28,11 +30,13 @@ interface trySupplier { } /** @since 0.0.2 */ + @SuppressWarnings("unused") @NotNull default trySupplier andThen(@Nullable tryFunction after) { if ( after != null ) return () -> after.apply(get()); + //noinspection unchecked return (trySupplier) this; } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/i/AbstractSyLock.java b/src/main/java/fybug/nulll/pdconcurrent/i/AbstractSyLock.java new file mode 100644 index 0000000000000000000000000000000000000000..f4dba533f5f736c24e3536589505c54df572b0fb --- /dev/null +++ b/src/main/java/fybug/nulll/pdconcurrent/i/AbstractSyLock.java @@ -0,0 +1,216 @@ +package fybug.nulll.pdconcurrent.i; +import java.util.function.Function; + +import fybug.nulll.pdconcurrent.SyLock; +import fybug.nulll.pdconcurrent.e.LockType; +import fybug.nulll.pdconcurrent.fun.tryFunction; +import fybug.nulll.pdconcurrent.fun.trySupplier; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; + +/** + *

读写锁管理基本框架.

+ * + * @author fybug + * @version 0.0.1 + * @since i 0.0.1 + */ +@SuppressWarnings("unused") +public abstract +class AbstractSyLock implements SyLock { + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param catchby {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @implNote 使用 {@link #lock(LockType)} 与 {@link #unlock()} 方法实现上锁与解锁 + */ + @Override + public + R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function catchby, + @Nullable Function finaby) + { + R o = null; + // 防止finally内的回调抛异常 + try { + try { + // 上锁 + lock(lockType); + // 主要内容 + o = run.get(); + } catch ( Exception e ) { + // 异常处理 + if ( catchby != null ) + o = catchby.apply(e); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } finally { + unlock(); + } + return o; + } + + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @implNote 使用 {@link #lock(LockType)} 与 {@link #unlock()} 方法实现上锁与解锁 + */ + @Override + public + R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { + R o = null; + // 防止finally内的回调抛异常 + try { + try { + // 上锁 + lock(lockType); + // 主要内容 + o = run.get(); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } finally { + unlock(); + } + return o; + } + + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param catchby {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @implNote 使用 {@link #trylock(LockType)} 与 {@link #unlock()} 方法实现上锁与解锁 + */ + @Override + public + R trylock(@NotNull LockType lockType, @NotNull tryFunction run, @Nullable Function catchby, + @Nullable Function finaby) + { + R o = null; + // 防止finally内的回调抛异常 + try { + try { + // 上锁 + o = run.apply(trylock(lockType)); + } catch ( Exception e ) { + // 异常处理 + if ( catchby != null ) + o = catchby.apply(e); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } finally { + unlock(); + } + return o; + } + + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @throws Exception {@inheritDoc} + * @implNote 使用 {@link #trylock(LockType)} 与 {@link #unlock()} 方法实现上锁与解锁 + */ + @Override + public + R trylock(@NotNull LockType lockType, @NotNull tryFunction run, @Nullable Function finaby) + throws Exception + { + R o = null; + // 防止finally内的回调抛异常 + try { + try { + // 上锁 + o = run.apply(trylock(lockType)); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } finally { + unlock(); + } + return o; + } + + /** + * 上锁函数 + * + * @param lockType 锁类型 + * + * @throws Exception 可能抛出的异常 + * @implSpec 在此处实现上锁功能 + */ + protected abstract + void lock(@NotNull LockType lockType) throws Exception; + + /** + * 尝试上锁函数 + * + * @param lockType 锁类型 + * + * @return 是否成功上锁 + * + * @implSpec 在此处实现尝试上锁功能 + */ + protected abstract + boolean trylock(@NotNull LockType lockType); + + /** + * 解锁函数 + * + * @implSpec 在此处实现解锁功能,解锁的类型按照最后上锁的类型处理 + */ + public abstract + void unlock(); + + /** + * 检查锁是否被占用 + * + * @return 是否被占用 + */ + public abstract + boolean isLocked(); + + /** + * 检查当前线程是否持有锁 + * + * @return 当前线程是否持有锁 + */ + public abstract + boolean isLockedCurrentThread(); +} diff --git a/src/main/java/fybug/nulll/pdconcurrent/i/Lock.java b/src/main/java/fybug/nulll/pdconcurrent/i/Lock.java new file mode 100644 index 0000000000000000000000000000000000000000..7c5a94f5d5f53a2b808cb076309ba50bdb92ba8f --- /dev/null +++ b/src/main/java/fybug/nulll/pdconcurrent/i/Lock.java @@ -0,0 +1,140 @@ +package fybug.nulll.pdconcurrent.i; +import java.util.function.Consumer; +import java.util.function.Function; + +import fybug.nulll.pdconcurrent.e.LockType; +import fybug.nulll.pdconcurrent.fun.tryRunnable; +import fybug.nulll.pdconcurrent.fun.trySupplier; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; + +/** + *

基础锁管理.

+ * 通过传入回调的方式隐藏内部的并发管理方法,并支持复用内部的try块,通过传入的回调插入到catch,finally块中执行
+ * {@code lock()}方法用于根据传入的{@link LockType}申请不同的锁类型进行执行
+ * 有可抛出异常的方法变体,可在传入的接口中抛出异常 + * + * @author fybug + * @version 0.0.1 + * @see LockType + * @since i 0.0.1 + */ +interface Lock { + /** + * 使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
+ * 所有回调均在并发域内执行 + * + * @param lockType 锁类型 + * @param run 带返回的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + * + * @implSpec 如果有传入 {@code finaby} 回调则返回值由{@code finaby}主导,传入{@code finaby}的值根据是否发生异常传入{@code run}的返回值或{@code catchby}的返回值
+ * 任意一个回调为空时直接穿透,使用上一个正确执行的值进行传递或者返回,传递值应默认为{@code null}用于应对{@code catchby}和{@code finaby}都为空但是发生了异常的情况 + */ + R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function catchby, + @Nullable Function finaby); + + /** + * 使用锁执行指定回调 + *

+ * {@link #lock(LockType, trySupplier, Function, Function)}的无返回变体 + * + * @param lockType 锁类型 + * @param run 执行的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调 + */ + default + void lock(@NotNull LockType lockType, @NotNull tryRunnable run, @Nullable Consumer catchby, + @Nullable Runnable finaby) + { + lock(lockType, () -> { + run.run(); + return null; + }, catchby == null ? null : e -> { + catchby.accept(e); + return null; + }, finaby == null ? null : _ -> { + finaby.run(); + return null; + }); + } + + /** + * 使用锁执行指定回调 + *

+ * {@link #lock(LockType, trySupplier, Function, Function)}的可抛异常变体
+ * 运行时改为使用try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出 + * + * @param lockType 锁类型 + * @param run 带返回的回调 + * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @implSpec 如果有传入 {@code finaby} 回调则返回值由{@code finaby}主导,传入{@code finaby}的值根据是否发生异常传入{@code run}的返回值或{@code null}
+ * 任意一个回调为空时直接穿透,使用上一个正确执行的值进行传递或者返回,发生异常会执行{@code finaby}但是不会返回内容 + */ + R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception; + + /** + * 使用锁执行指定回调 + *

+ * {@link #lock(LockType, trySupplier, Function)}的简易变体 + * + * @param lockType 锁类型 + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + R lock(@NotNull LockType lockType, @NotNull trySupplier run) throws Exception + { return lock(lockType, run, null); } + + /** + * 使用锁执行指定回调 + *

+ * {@link #lock(LockType, trySupplier, Function)}的无返回变体 + * + * @param lockType 锁类型 + * @param run 执行的回调 + * @param finaby 进入finally块后的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void lock(@NotNull LockType lockType, @NotNull tryRunnable run, @Nullable Runnable finaby) throws Exception { + lock(lockType, () -> { + run.run(); + return null; + }, finaby == null ? null : _ -> { + finaby.run(); + return null; + }); + } + + /** + * 使用锁执行指定回调 + *

+ * {@link #lock(LockType, tryRunnable, Runnable)}的简易变体 + * + * @param lockType 锁类型 + * @param run 执行的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void lock(@NotNull LockType lockType, @NotNull tryRunnable run) throws Exception + { lock(lockType, run, null); } +} diff --git a/src/main/java/fybug/nulll/pdconcurrent/i/ReadWriteLock.java b/src/main/java/fybug/nulll/pdconcurrent/i/ReadWriteLock.java new file mode 100644 index 0000000000000000000000000000000000000000..63a7d1ea5ad2e3546443f33dd218180566acd366 --- /dev/null +++ b/src/main/java/fybug/nulll/pdconcurrent/i/ReadWriteLock.java @@ -0,0 +1,203 @@ +package fybug.nulll.pdconcurrent.i; +import java.util.function.Consumer; +import java.util.function.Function; + +import fybug.nulll.pdconcurrent.e.LockType; +import fybug.nulll.pdconcurrent.fun.tryRunnable; +import fybug.nulll.pdconcurrent.fun.trySupplier; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; + +/** + *

并发管理读写支持拓展.

+ * {@link Lock}的拓展,增加{@code read()}、{@code write()}类方法用于隐藏{@link LockType}参数 + * + * @author fybug + * @version 0.0.1 + * @see LockType#READ + * @see LockType#WRITE + * @see Lock + * @since i 0.0.1 + */ +@SuppressWarnings("unused") +public +interface ReadWriteLock extends Lock { + /** + * 使用读锁执行指定回调 + *

+ * {@link #lock(LockType, trySupplier, Function, Function)}指定读锁的变种 + * + * @param run 带返回的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + */ + default + R read(@NotNull trySupplier run, @Nullable Function catchby, @Nullable Function finaby) + { return lock(LockType.READ, run, catchby, finaby); } + + /** + * 使用读锁执行指定回调 + *

+ * {@link #lock(LockType, tryRunnable, Consumer, Runnable)}指定读锁的变种 + * + * @param run 执行的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调 + */ + default + void read(@NotNull tryRunnable run, @Nullable Consumer catchby, @Nullable Runnable finaby) + { lock(LockType.READ, run, catchby, finaby); } + + /** + * 使用读锁执行指定回调 + *

+ * {@link #lock(LockType, trySupplier, Function)}指定读锁的变种 + * + * @param run 带返回的回调 + * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + R read(@NotNull trySupplier run, @Nullable Function finaby) throws Exception + { return lock(LockType.READ, run, finaby); } + + /** + * 使用读锁执行指定回调 + *

+ * {@link #lock(LockType, trySupplier)}指定读锁的变种 + * + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + R read(@NotNull trySupplier run) throws Exception + { return lock(LockType.READ, run); } + + /** + * 使用读锁执行指定回调 + *

+ * {@link #lock(LockType, tryRunnable, Runnable)}指定读锁的变种 + * + * @param run 执行的回调 + * @param finaby 进入finally块后的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void read(@NotNull tryRunnable run, @Nullable Runnable finaby) throws Exception + { lock(LockType.READ, run, finaby); } + + /** + * 使用读锁执行指定回调 + *

+ * {@link #lock(LockType, tryRunnable)}指定读锁的变种 + * + * @param run 执行的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void read(@NotNull tryRunnable run) throws Exception + { lock(LockType.READ, run); } + + + /** + * 使用写锁执行指定回调 + *

+ * {@link #lock(LockType, trySupplier, Function, Function)}指定写锁的变种 + * + * @param run 带返回的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + */ + default + R write(@NotNull trySupplier run, @Nullable Function catchby, @Nullable Function finaby) + { return lock(LockType.WRITE, run, catchby, finaby); } + + /** + * 使用写锁执行指定回调 + *

+ * {@link #lock(LockType, tryRunnable, Consumer, Runnable)}指定写锁的变种 + * + * @param run 执行的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调 + */ + default + void write(@NotNull tryRunnable run, @Nullable Consumer catchby, @Nullable Runnable finaby) + { lock(LockType.WRITE, run, catchby, finaby); } + + /** + * 使用写锁执行指定回调 + *

+ * {@link #lock(LockType, trySupplier, Function)}指定写锁的变种 + * + * @param run 带返回的回调 + * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + R write(@NotNull trySupplier run, @Nullable Function finaby) throws Exception + { return lock(LockType.WRITE, run, finaby); } + + /** + * 使用写锁执行指定回调 + *

+ * {@link #lock(LockType, trySupplier)}指定写锁的变种 + * + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + R write(@NotNull trySupplier run) throws Exception + { return lock(LockType.WRITE, run); } + + /** + * 使用写锁执行指定回调 + *

+ * {@link #lock(LockType, tryRunnable, Runnable)}指定写锁的变种 + * + * @param run 执行的回调 + * @param finaby 进入finally块后的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void write(@NotNull tryRunnable run, @Nullable Runnable finaby) throws Exception + { lock(LockType.WRITE, run, finaby); } + + /** + * 使用写锁执行指定回调 + *

+ * {@link #lock(LockType, tryRunnable)}指定写锁的变种 + * + * @param run 执行的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void write(@NotNull tryRunnable run) throws Exception + { lock(LockType.WRITE, run); } +} diff --git a/src/main/java/fybug/nulll/pdconcurrent/i/TryLock.java b/src/main/java/fybug/nulll/pdconcurrent/i/TryLock.java new file mode 100644 index 0000000000000000000000000000000000000000..b6d120fe914bdeb39884f50aa0b64e8ebb76545e --- /dev/null +++ b/src/main/java/fybug/nulll/pdconcurrent/i/TryLock.java @@ -0,0 +1,142 @@ +package fybug.nulll.pdconcurrent.i; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; +import java.util.function.Function; + +import fybug.nulll.pdconcurrent.e.LockType; +import fybug.nulll.pdconcurrent.fun.tryConsumer; +import fybug.nulll.pdconcurrent.fun.tryFunction; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; + +/** + *

允许尝试上锁的并发管理.

+ * {@link Lock}的拓展,增加{@code trylock()}类方法用于适配需要立刻判断是否获取到锁并即刻往下执行的情况 + * + * @author fybug + * @version 0.0.1 + * @since i 0.0.1 + */ +interface TryLock { + /** + * 尝试使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,但需要注意该方法并非一定能成功获取到锁,可通过{@code run}回调参数中传入的{@code boolean}判断是否成功获取到了锁
+ * 运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
+ * 若成功获取锁则所有回调均在并发域内执行 + * + * @param lockType 锁类型 + * @param run 带返回的回调,传入参数是否获取到锁 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + * + * @implSpec 该方法实现时应尽量使用如 {@link ReentrantLock#tryLock()} 之类的方法获取锁,并将是否成功获取传入{@code run}回调中
+ * 如果有传入 {@code finaby} 回调则返回值由{@code finaby}主导,传入{@code finaby}的值根据是否发生异常传入{@code run}的返回值或{@code catchby}的返回值
+ * 任意一个回调为空时直接穿透,使用上一个正确执行的值进行传递或者返回,传递值应默认为{@code null}用于应对{@code catchby}和{@code finaby}都为空但是发生了异常的情况 + */ + R trylock(@NotNull LockType lockType, @NotNull tryFunction run, @Nullable Function catchby, + @Nullable Function finaby); + + /** + * 尝试使用锁执行指定回调 + *

+ * {@link #trylock(LockType, tryFunction, Function, Function)}的无返回变体 + * + * @param lockType 锁类型 + * @param run 执行的回调,传入参数是否获取到锁 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调 + */ + default + void trylock(@NotNull LockType lockType, @NotNull tryConsumer run, @Nullable Consumer catchby, + @Nullable Runnable finaby) + { + trylock(lockType, b -> { + run.accept(b); + return null; + }, catchby == null ? null : e -> { + catchby.accept(e); + return null; + }, finaby == null ? null : _ -> { + finaby.run(); + return null; + }); + } + + /** + * 尝试使用锁执行指定回调 + *

+ * {@link #trylock(LockType, tryFunction, Function, Function)}的可抛异常变体
+ * 运行时改为使用try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出 + * + * @param lockType 锁类型 + * @param run 带返回的回调,传入参数是否获取到锁 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值,遇到异常传入{@code null} + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @implSpec 该方法实现时应尽量使用如 {@link ReentrantLock#tryLock()} 之类的方法获取锁,并将是否成功获取传入{@code run}回调中
+ * 如果有传入 {@code finaby} 回调则返回值由{@code finaby}主导,传入{@code finaby}的值根据是否发生异常传入{@code run}的返回值或{@code catchby}的返回值
+ * 任意一个回调为空时直接穿透,使用上一个正确执行的值进行传递或者返回,传递值应默认为{@code null}用于应对{@code catchby}和{@code finaby}都为空但是发生了异常的情况 + */ + R trylock(@NotNull LockType lockType, @NotNull tryFunction run, @Nullable Function finaby) + throws Exception; + + /** + * 尝试使用锁执行指定回调 + *

+ * {@link #trylock(LockType, tryFunction, Function)}的简易变体 + * + * @param lockType 锁类型 + * @param run 带返回的回调,传入参数是否获取到锁 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + R trylock(@NotNull LockType lockType, @NotNull tryFunction run) throws Exception + { return trylock(lockType, run, null); } + + /** + * 尝试使用锁执行指定回调 + *

+ * {@link #trylock(LockType, tryFunction, Function)}的无返回变体 + * + * @param lockType 锁类型 + * @param run 执行的回调,传入参数是否获取到锁 + * @param finaby 进入finally块后的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void trylock(@NotNull LockType lockType, @NotNull tryConsumer run, @Nullable Runnable finaby) throws Exception { + trylock(lockType, b -> { + run.accept(b); + return null; + }, finaby == null ? null : _ -> { + finaby.run(); + return null; + }); + } + + /** + * 尝试使用锁执行指定回调 + *

+ * {@link #trylock(LockType, tryConsumer, Runnable)}的简易变体 + * + * @param lockType 锁类型 + * @param run 带返回的回调,传入参数是否获取到锁 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void trylock(@NotNull LockType lockType, @NotNull tryConsumer run) throws Exception + { trylock(lockType, run, null); } +} diff --git a/src/main/java/fybug/nulll/pdconcurrent/i/TryReadWriteLock.java b/src/main/java/fybug/nulll/pdconcurrent/i/TryReadWriteLock.java new file mode 100644 index 0000000000000000000000000000000000000000..a3ff383407714c5af311f74bcc25c79a332805ea --- /dev/null +++ b/src/main/java/fybug/nulll/pdconcurrent/i/TryReadWriteLock.java @@ -0,0 +1,204 @@ +package fybug.nulll.pdconcurrent.i; +import java.util.function.Consumer; +import java.util.function.Function; + +import fybug.nulll.pdconcurrent.e.LockType; +import fybug.nulll.pdconcurrent.fun.tryConsumer; +import fybug.nulll.pdconcurrent.fun.tryFunction; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; + +/** + *

TryLock 读写支持拓展.

+ * {@link TryLock}的拓展,增加{@code tryread()}、{@code trywrite()}类方法用于隐藏{@link LockType}参数 + * + * @author fybug + * @version 0.0.1 + * @see LockType#READ + * @see LockType#WRITE + * @see TryLock + * @since i 0.0.1 + */ +@SuppressWarnings("unused") +public +interface TryReadWriteLock extends TryLock { + /** + * 尝试使用读锁执行指定回调 + *

+ * {@link #trylock(LockType, tryFunction, Function, Function)}指定读锁的变种 + * + * @param run 带返回的回调,传入参数是否获取到锁 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + */ + default + R tryread(@NotNull tryFunction run, @Nullable Function catchby, + @Nullable Function finaby) + { return trylock(LockType.READ, run, catchby, finaby); } + + /** + * 尝试使用读锁执行指定回调 + *

+ * {@link #trylock(LockType, tryConsumer, Consumer, Runnable)}指定读锁的变种 + * + * @param run 执行的回调,传入参数是否获取到锁 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调 + */ + default + void tryread(@NotNull tryConsumer run, @Nullable Consumer catchby, @Nullable Runnable finaby) + { trylock(LockType.READ, run, catchby, finaby); } + + /** + * 尝试使用读锁执行指定回调 + *

+ * {@link #trylock(LockType, tryFunction, Function)}指定读锁的变种 + * + * @param run 带返回的回调,传入参数是否获取到锁 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值,遇到异常传入{@code null} + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + R tryread(@NotNull tryFunction run, @Nullable Function finaby) throws Exception + { return trylock(LockType.READ, run, finaby); } + + /** + * 尝试使用读锁执行指定回调 + *

+ * {@link #trylock(LockType, tryFunction)}指定读锁的变种 + * + * @param run 带返回的回调,传入参数是否获取到锁 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + R tryread(@NotNull tryFunction run) throws Exception + { return trylock(LockType.READ, run); } + + /** + * 尝试使用读锁执行指定回调 + *

+ * {@link #trylock(LockType, tryConsumer, Runnable)}指定读锁的变种 + * + * @param run 执行的回调,传入参数是否获取到锁 + * @param finaby 进入finally块后的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void tryread(@NotNull tryConsumer run, @Nullable Runnable finaby) throws Exception + { trylock(LockType.READ, run, finaby); } + + /** + * 尝试使用读锁执行指定回调 + *

+ * {@link #trylock(LockType, tryConsumer)}指定读锁的变种 + * + * @param run 带返回的回调,传入参数是否获取到锁 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void tryread(@NotNull tryConsumer run) throws Exception + { trylock(LockType.READ, run); } + + /** + * 尝试使用写锁执行指定回调 + *

+ * {@link #trylock(LockType, tryFunction, Function, Function)}指定写锁的变种 + * + * @param run 带返回的回调,传入参数是否获取到锁 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + */ + default + R trywrite(@NotNull tryFunction run, @Nullable Function catchby, + @Nullable Function finaby) + { return trylock(LockType.WRITE, run, catchby, finaby); } + + /** + * 尝试使用写锁执行指定回调 + *

+ * {@link #trylock(LockType, tryConsumer, Consumer, Runnable)}指定写锁的变种 + * + * @param run 执行的回调,传入参数是否获取到锁 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调 + */ + default + void trywrite(@NotNull tryConsumer run, @Nullable Consumer catchby, @Nullable Runnable finaby) + { trylock(LockType.WRITE, run, catchby, finaby); } + + /** + * 尝试使用写锁执行指定回调 + *

+ * {@link #trylock(LockType, tryFunction, Function)}指定写锁的变种 + * + * @param run 带返回的回调,传入参数是否获取到锁 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值,遇到异常传入{@code null} + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + R trywrite(@NotNull tryFunction run, @Nullable Function finaby) throws Exception + { return trylock(LockType.WRITE, run, finaby); } + + /** + * 尝试使用写锁执行指定回调 + *

+ * {@link #trylock(LockType, tryFunction)}指定写锁的变种 + * + * @param run 带返回的回调,传入参数是否获取到锁 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + R trywrite(@NotNull tryFunction run) throws Exception + { return trylock(LockType.WRITE, run); } + + /** + * 尝试使用写锁执行指定回调 + *

+ * {@link #trylock(LockType, tryConsumer, Runnable)}指定写锁的变种 + * + * @param run 执行的回调,传入参数是否获取到锁 + * @param finaby 进入finally块后的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void trywrite(@NotNull tryConsumer run, @Nullable Runnable finaby) throws Exception + { trylock(LockType.WRITE, run, finaby); } + + /** + * 尝试使用写锁执行指定回调 + *

+ * {@link #trylock(LockType, tryConsumer)}指定写锁的变种 + * + * @param run 带返回的回调,传入参数是否获取到锁 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + */ + default + void trywrite(@NotNull tryConsumer run) throws Exception + { trylock(LockType.WRITE, run); } +} diff --git a/src/main/java/fybug/nulll/pdconcurrent/i/package-info.java b/src/main/java/fybug/nulll/pdconcurrent/i/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..6ced81b027b2698770bcba5df855e639b3fa8731 --- /dev/null +++ b/src/main/java/fybug/nulll/pdconcurrent/i/package-info.java @@ -0,0 +1,9 @@ +/** + *

接口包.

+ * 提供基础功能接口与部分功能框架实现 + * + * @author fybug + * @version 0.0.1 + * @since PDConcurrent 0.1.2 + */ +package fybug.nulll.pdconcurrent.i; \ No newline at end of file diff --git a/src/main/java/fybug/nulll/pdconcurrent/ObjLock.java b/src/main/java/fybug/nulll/pdconcurrent/lock/ObjLock.java similarity index 70% rename from src/main/java/fybug/nulll/pdconcurrent/ObjLock.java rename to src/main/java/fybug/nulll/pdconcurrent/lock/ObjLock.java index 9f138ec391d75dc908c7110d7b2076d98737d598..250ec5b75d0d565d1c7cf036552746daf10be054 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/ObjLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/lock/ObjLock.java @@ -1,7 +1,9 @@ -package fybug.nulll.pdconcurrent; +package fybug.nulll.pdconcurrent.lock; import java.util.function.Function; +import fybug.nulll.pdconcurrent.SyLock; import fybug.nulll.pdconcurrent.e.LockType; +import fybug.nulll.pdconcurrent.fun.tryFunction; import fybug.nulll.pdconcurrent.fun.trySupplier; import jakarta.annotation.Nullable; import jakarta.validation.constraints.NotNull; @@ -13,13 +15,13 @@ import lombok.Getter; *

* 使用并发管理: * {@snippet lang = java: + * import fybug.nulll.pdconcurrent.SyLock; * public final SyLock lock = new ObjLock(); * public static void main(String[] args) { * lock.read(() -> System.out.println("asd")); * }} * 不使用: * {@snippet lang = java: - * public final Object lock = new Object(); * public static void main(String[] args) { * synchronized ( lock ){ * System.out.println("asd"); @@ -27,10 +29,10 @@ import lombok.Getter; * }} * * @author fybug - * @version 0.1.0 - * @see SyLock - * @since PDConcurrent 0.0.1 + * @version 0.1.2 + * @since lock 0.0.1 */ +@SuppressWarnings("unused") @Getter public class ObjLock implements SyLock { @@ -67,7 +69,6 @@ class ObjLock implements SyLock { * @return {@inheritDoc} * * @implNote 使用 {@code synchronized( Object )} 实现的隐式并发域 - * @see SyLock#lock(LockType, trySupplier, Function, Function) * @since 0.1.0 */ @Override @@ -121,12 +122,11 @@ class ObjLock implements SyLock { * @return {@inheritDoc} * * @implNote 使用 {@code synchronized( Object )} 实现的隐式并发域 - * @see SyLock#trylock(LockType, trySupplier, Function) - * @since 0.1.0 + * @since 0.1.2 */ @Override public - R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { + R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { R o = null; // 不上锁 if ( lockType == LockType.NOLOCK ) { @@ -153,4 +153,42 @@ class ObjLock implements SyLock { } return o; } + + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param catchby {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @since 0.1.2 + */ + @Override + public + R trylock(@NotNull LockType lockType, @NotNull tryFunction run, @Nullable Function catchby, + @Nullable Function finaby) + { return lock(lockType, () -> run.apply(true), catchby, finaby); } + + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @throws Exception {@inheritDoc} + * @since 0.1.2 + */ + @Override + public + R trylock(@NotNull LockType lockType, @NotNull tryFunction run, @Nullable Function finaby) + throws Exception + { return lock(lockType, () -> run.apply(true), finaby); } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/RWLock.java b/src/main/java/fybug/nulll/pdconcurrent/lock/RWLock.java similarity index 42% rename from src/main/java/fybug/nulll/pdconcurrent/RWLock.java rename to src/main/java/fybug/nulll/pdconcurrent/lock/RWLock.java index e5ef8d5802b9da5694e8fb3b4c0f6397ad6b836d..ea25e360c859acb7df248d5ad048cc29df67929b 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/RWLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/lock/RWLock.java @@ -1,19 +1,19 @@ -package fybug.nulll.pdconcurrent; +package fybug.nulll.pdconcurrent.lock; +import java.util.LinkedList; +import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Function; import fybug.nulll.pdconcurrent.e.LockType; -import fybug.nulll.pdconcurrent.fun.trySupplier; -import jakarta.annotation.Nullable; +import fybug.nulll.pdconcurrent.i.AbstractSyLock; import jakarta.validation.constraints.NotNull; import lombok.Getter; /** *

使用{@link ReentrantReadWriteLock}实现的并发管理.

* 使用{@link ReentrantReadWriteLock}实现并发域,读写锁均为标准实现,支持通过{@link #toread()}进行锁降级
- * 使用了可中断的上锁操作{@link ReentrantReadWriteLock.ReadLock#lockInterruptibly()}和{@link ReentrantReadWriteLock.WriteLock#lockInterruptibly()}
- * 支持使用{@link #newReadCondition()}{@link #newWriteCondition()}获取{@link Condition},通过{@link #isLocked()}{@link #isWriteLocked()}{@link #isReadLocked()}检查是否被占用
+ * 使用可中断的上锁操作{@link ReentrantReadWriteLock.ReadLock#lockInterruptibly()}和{@link ReentrantReadWriteLock.WriteLock#lockInterruptibly()}实现上锁
+ * 支持使用{@link #newReadCondition()}{@link #newWriteCondition()}获取{@link Condition} *

* 使用并发管理: * {@snippet lang = java: @@ -46,17 +46,16 @@ import lombok.Getter; * }} * * @author fybug - * @version 0.1.0 - * @see SyLock - * @see LockType + * @version 0.1.1 * @see ReentrantReadWriteLock * @see ReentrantReadWriteLock.ReadLock * @see ReentrantReadWriteLock.WriteLock - * @since PDConcurrent 0.0.1 + * @since lock 0.0.1 */ +@SuppressWarnings("unused") @Getter public -class RWLock implements SyLock { +class RWLock extends AbstractSyLock { /** 锁 */ private final ReentrantReadWriteLock LOCK; /** 读锁 */ @@ -65,12 +64,22 @@ class RWLock implements SyLock { private final ReentrantReadWriteLock.WriteLock Write_LOCK; /** * 每个线程的锁状态记录 - *

- * 不上锁为{@code null}
- * 读锁为{@code 1}
- * 写锁为{@code 2} + * + * @see LockType + */ + private final ThreadLocal> LOCK_STATE = new ThreadLocal<>(); + /** + * 读锁计数 + * + * @since 0.1.1 */ - private final ThreadLocal LOCK_STATE = new ThreadLocal<>(); + private final AtomicLong READ_LOCK_COUNTER = new AtomicLong(); + /** + * 写锁计数 + * + * @since 0.1.1 + */ + private final AtomicLong WRITE_LOCK_COUNTER = new AtomicLong(); /** * 构建并发管理 @@ -103,140 +112,134 @@ class RWLock implements SyLock { } /** - * {@inheritDoc} + * 获取当前线程锁记录 * - * @param lockType {@inheritDoc} - * @param run {@inheritDoc} - * @param catchby {@inheritDoc} - * @param finaby {@inheritDoc} - * @param {@inheritDoc} + * @return 锁类型列表 * - * @return {@inheritDoc} - * - * @implNote 使用 {@link ReentrantReadWriteLock} 实现的并发域,上锁通过{@link #tolock(LockType)}进行 - * @see SyLock#lock(LockType, trySupplier, Function, Function) - * @see #tolock(LockType) - * @see #tounlock() - * @since 0.1.0 + * @since 0.1.1 */ - @Override - public - R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function catchby, - @Nullable Function finaby) - { - R o = null; - // 清空当前线程的状态 - LOCK_STATE.remove(); - // 防止finally内的回调抛异常 - try { - try { - // 上锁 - tolock(lockType); - // 主要内容 - o = run.get(); - } catch ( Exception e ) { - // 异常处理 - if ( catchby != null ) - o = catchby.apply(e); - } finally { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } - } finally { - // 解锁 - tounlock(); + @NotNull + private + LinkedList getCurrentThreadLockState() { + // 获取记录 + var l = LOCK_STATE.get(); + // 保证记录存在 + if ( l == null ) { + l = new LinkedList<>(); + LOCK_STATE.set(l); } - return o; + return l; } /** * {@inheritDoc} * * @param lockType {@inheritDoc} - * @param run {@inheritDoc} - * @param finaby {@inheritDoc} - * @param {@inheritDoc} - * - * @return {@inheritDoc} * - * @implNote 使用 {@link ReentrantReadWriteLock} 实现的并发域,上锁通过{@link #tolock(LockType)}进行 - * @see SyLock#trylock(LockType, trySupplier, Function) - * @see #tolock(LockType) - * @see #tounlock() - * @since 0.1.0 + * @throws Exception {@inheritDoc} + * @implNote 使用 {@link ReentrantReadWriteLock} 实现的并发域,使用了{@code lockInterruptibly()}进行可中断的上锁操作
+ * 会记录本次锁类型并记录读写锁的计数 + * @since 0.1.1 */ @Override - public - R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { - R o = null; - // 清空当前线程的状态 - LOCK_STATE.remove(); - // 防止finally内的回调抛异常 - try { - try { - // 上锁 - tolock(lockType); - // 主要内容 - o = run.get(); - } finally { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); + protected + void lock(@NotNull LockType lockType) throws InterruptedException { + // 获取记录列表 + var l = getCurrentThreadLockState(); + // 检查锁类型进行上锁,并更新对应锁计数 + if ( lockType != LockType.NOLOCK ) { + if ( lockType == LockType.READ ) { + Read_LOCK.lockInterruptibly(); + READ_LOCK_COUNTER.getAndIncrement(); + } else if ( lockType == LockType.WRITE ) { + Write_LOCK.lockInterruptibly(); + WRITE_LOCK_COUNTER.getAndIncrement(); } - } finally { - // 解锁 - tounlock(); + // 记录本次锁类型 + l.add(lockType); + } else if ( l.isEmpty() ) { + LOCK_STATE.remove(); } - return o; } /** - * 根据指定类型上锁 - *

- * 使用了可中断的上锁操作{@link ReentrantReadWriteLock.ReadLock#lockInterruptibly()}和{@link ReentrantReadWriteLock.WriteLock#lockInterruptibly()}
- * 同时更新{@link #LOCK_STATE}记录 + * {@inheritDoc} * - * @param lockType 锁类型 + * @param lockType {@inheritDoc} * - * @throws InterruptedException 上锁过程中被中断 - * @see #LOCK_STATE - * @see LockType - * @since 0.1.0 + * @return {@inheritDoc} + * + * @implNote 使用 {@link ReentrantReadWriteLock} 实现的并发域,使用了{@code trylock()}实现
+ * 会记录本次锁类型并记录读写锁的计数 + * @since 0.1.1 */ - private - void tolock(@NotNull LockType lockType) throws InterruptedException { + @Override + protected + boolean trylock(@NotNull LockType lockType) { + // 获取记录列表 + var l = getCurrentThreadLockState(); + // 是否成功 + boolean success = false; + + // 检查锁类型并上锁 if ( lockType != LockType.NOLOCK ) { - if ( lockType == LockType.READ ) { - // 读锁 - Read_LOCK.lockInterruptibly(); - LOCK_STATE.set((short) 1); - } else if ( lockType == LockType.WRITE ) { - // 写锁 - Write_LOCK.lockInterruptibly(); - LOCK_STATE.set((short) 2); - } + if ( lockType == LockType.READ ) + success = Read_LOCK.tryLock(); + else if ( lockType == LockType.WRITE ) + success = Write_LOCK.tryLock(); + } + // 是否成功 + if ( success ) { + // 记录本次锁类型 + l.add(lockType); + // 更新对应锁计数 + if ( lockType == LockType.READ ) + READ_LOCK_COUNTER.getAndIncrement(); + else //noinspection ConstantValue + if ( lockType == LockType.WRITE ) + WRITE_LOCK_COUNTER.getAndIncrement(); + } else if ( l.isEmpty() ) { + LOCK_STATE.remove(); } + + return success; } /** - * 根据状态解锁 - *

- * 根据{@link #LOCK_STATE}的状态调用对应的解锁动作
- * 成功后清空{@link #LOCK_STATE}内容 + * {@inheritDoc} * - * @see #LOCK_STATE - * @since 0.1.0 + * @implNote 通过 {@link #LOCK_STATE} 检查当前线程是否持有锁,持有时才会运行{@code unlock()}
+ * 会更新读写锁的计数 + * @since 0.1.1 */ - private - void tounlock() { - // 根据实际状态解锁 - if ( LOCK_STATE.get() == 1 ) + @Override + public + void unlock() { + // 获取记录列表 + var l = LOCK_STATE.get(); + // 没有记录 + if ( l == null ) + return; + // 没有上锁 + if ( l.isEmpty() ) { + LOCK_STATE.remove(); + return; + } + + // 获取最后锁类型 + var lockType = l.removeLast(); + // 检查锁类型解锁,并更新对应锁计数 + if ( lockType == LockType.READ ) { Read_LOCK.unlock(); - else if ( LOCK_STATE.get() == 2 ) + READ_LOCK_COUNTER.getAndDecrement(); + } else if ( lockType == LockType.WRITE ) { Write_LOCK.unlock(); - // 清除记录数据 - LOCK_STATE.remove(); + WRITE_LOCK_COUNTER.getAndDecrement(); + } + + // 记录清空 + if ( l.isEmpty() ) + LOCK_STATE.remove(); } /** @@ -244,18 +247,34 @@ class RWLock implements SyLock { *

* 如果当前状态为写锁则会降级为读锁,否则不进行操作 * - * @return 是否成功降级 + * @return 是否为读锁 * - * @see #LOCK_STATE * @since 0.1.0 */ public boolean toread() { - // 转为读锁 - if ( LOCK_STATE.get() == 2 ) { + // 获取记录列表 + var l = getCurrentThreadLockState(); + // 没有上锁 + if ( l.isEmpty() ) { + LOCK_STATE.remove(); + return false; + } + + // 获取最后锁类型 + var lockType = l.getLast(); + // 检查锁类型进行处理,并更新对应锁计数 + if ( lockType == LockType.READ ) + return true; + else if ( lockType == LockType.WRITE ) { + // 锁降级 Read_LOCK.lock(); Write_LOCK.unlock(); - LOCK_STATE.set((short) 1); + // 更新记录 + l.set(l.size() - 1, LockType.WRITE); + // 更新计数 + WRITE_LOCK_COUNTER.getAndDecrement(); + READ_LOCK_COUNTER.getAndIncrement(); return true; } return false; @@ -268,18 +287,19 @@ class RWLock implements SyLock { * * @since 0.1.0 */ + @Override public - boolean isLocked() { return isReadLocked() || isWriteLocked(); } + boolean isLocked() { return isWriteLocked() || isReadLocked(); } /** * 检查读锁是否被占用 * - * @return 是否被占用 + * @return 锁是否被占用,写锁被占用也会返回{@code true} * * @since 0.1.0 */ public - boolean isReadLocked() { return LOCK_STATE.get() == 1; } + boolean isReadLocked() { return isWriteLocked() || READ_LOCK_COUNTER.get() > 0; } /** * 检查写锁是否被占用 @@ -289,7 +309,64 @@ class RWLock implements SyLock { * @since 0.1.0 */ public - boolean isWriteLocked() { return LOCK_STATE.get() == 2; } + boolean isWriteLocked() { return WRITE_LOCK_COUNTER.get() > 0; } + + /** + * 检查当前线程是否持有锁 + * + * @return 当前线程是否拥有锁 + * + * @since 0.1.1 + */ + @Override + public + boolean isLockedCurrentThread() { return isWriteLockedCurrentThread() || isReadLockedCurrentThread(); } + + /** + * 检查当前线程是否持有读锁 + * + * @return 当前线程是否持有锁,持有写锁也会返回{@code true} + * + * @since 0.1.1 + */ + public + boolean isReadLockedCurrentThread() { + // 获取锁队列 + var l = LOCK_STATE.get(); + // 没有记录 + if ( l == null ) + return false; + // 没有上锁 + if ( l.isEmpty() ) { + LOCK_STATE.remove(); + return false; + } + // 检查是否占用读锁 + return l.contains(LockType.WRITE) || l.contains(LockType.READ); + } + + /** + * 检查当前线程是否持有写锁 + * + * @return 当前线程是否持有锁 + * + * @since 0.1.1 + */ + public + boolean isWriteLockedCurrentThread() { + // 获取锁队列 + var l = LOCK_STATE.get(); + // 没有记录 + if ( l == null ) + return false; + // 没有上锁 + if ( l.isEmpty() ) { + LOCK_STATE.remove(); + return false; + } + // 检查是否占用读锁 + return l.contains(LockType.WRITE); + } /** * 获取读锁{@link Condition} diff --git a/src/main/java/fybug/nulll/pdconcurrent/ReLock.java b/src/main/java/fybug/nulll/pdconcurrent/lock/ReLock.java similarity index 50% rename from src/main/java/fybug/nulll/pdconcurrent/ReLock.java rename to src/main/java/fybug/nulll/pdconcurrent/lock/ReLock.java index 8defe87a0e2d7e71a7607d008962877a8512b2fc..3defce9ff02909fc9ea19a16f8e005a97bd2bd73 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/ReLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/lock/ReLock.java @@ -1,19 +1,17 @@ -package fybug.nulll.pdconcurrent; +package fybug.nulll.pdconcurrent.lock; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Function; import fybug.nulll.pdconcurrent.e.LockType; -import fybug.nulll.pdconcurrent.fun.trySupplier; -import jakarta.annotation.Nullable; +import fybug.nulll.pdconcurrent.i.AbstractSyLock; import jakarta.validation.constraints.NotNull; import lombok.Getter; /** *

使用{@link ReentrantLock}实现的并发管理.

* 使用{@link ReentrantLock}实现并发域,读写锁均为同一个实现
- * 使用了可中断的上锁操作{@link ReentrantLock#lockInterruptibly()}
- * 支持使用{@link #newCondition()}获取{@link Condition},通过{@link #isLocked()}检查是否被占用 + * 使用了可中断的上锁操作{@link ReentrantLock#lockInterruptibly()}实现
+ * 支持使用{@link #newCondition()}获取{@link Condition} *

* 使用并发管理: * {@snippet lang = java: @@ -36,14 +34,14 @@ import lombok.Getter; * }} * * @author fybug - * @version 0.1.0 - * @see SyLock + * @version 0.1.1 * @see ReentrantLock - * @since PDConcurrent 0.0.1 + * @since lock 0.0.1 */ +@SuppressWarnings("unused") @Getter public -class ReLock implements SyLock { +class ReLock extends AbstractSyLock { /** 锁 */ private final ReentrantLock LOCK; @@ -77,85 +75,47 @@ class ReLock implements SyLock { * {@inheritDoc} * * @param lockType {@inheritDoc} - * @param run {@inheritDoc} - * @param catchby {@inheritDoc} - * @param finaby {@inheritDoc} - * @param {@inheritDoc} - * - * @return {@inheritDoc} * + * @throws InterruptedException 所在线程被中断 * @implNote 使用 {@link ReentrantLock} 实现的并发域,使用了{@link ReentrantLock#lockInterruptibly()}进行可中断的上锁操作 - * @see SyLock#lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 + * @since 0.1.1 */ @Override - public - R lock(@NotNull LockType lockType, trySupplier run, @Nullable Function catchby, - @Nullable Function finaby) - { - R o = null; - // 防止finally内的回调抛异常 - try { - try { - // 上锁 - if ( lockType != LockType.NOLOCK ) - LOCK.lockInterruptibly(); - // 主要内容 - o = run.get(); - } catch ( Exception e ) { - // 异常处理 - if ( catchby != null ) - o = catchby.apply(e); - } finally { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } - } finally { - // 解锁 - if ( lockType != LockType.NOLOCK && LOCK.isLocked() ) - LOCK.unlock(); - } - return o; + protected + void lock(@NotNull LockType lockType) throws InterruptedException { + if ( lockType != LockType.NOLOCK ) + LOCK.lockInterruptibly(); } /** * {@inheritDoc} * * @param lockType {@inheritDoc} - * @param run {@inheritDoc} - * @param finaby {@inheritDoc} - * @param {@inheritDoc} * * @return {@inheritDoc} * - * @implNote 使用 {@link ReentrantLock} 实现的并发域,使用了{@link ReentrantLock#lockInterruptibly() - * @see SyLock#trylock(LockType, trySupplier, Function) - * @since 0.1.0 + * @implNote 使用 {@link ReentrantLock} 实现的并发域,使用了{@link ReentrantLock#tryLock()}实现 + * @since 0.1.1 + */ + @Override + protected + boolean trylock(@NotNull LockType lockType) { + if ( lockType != LockType.NOLOCK ) + return LOCK.tryLock(); + return false; + } + + /** + * {@inheritDoc} + * + * @implNote 使用 {@link ReentrantLock#isHeldByCurrentThread()} 检查当前线程是否持有锁,持有时才会运行{@link ReentrantLock#unlock()} + * @since 0.1.1 */ @Override public - R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { - R o = null; - // 防止finally内的回调抛异常 - try { - try { - // 上锁 - if ( lockType != LockType.NOLOCK ) - LOCK.lockInterruptibly(); - // 主要内容 - o = run.get(); - } finally { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } - } finally { - // 解锁 - if ( lockType != LockType.NOLOCK && LOCK.isLocked() ) - LOCK.unlock(); - } - return o; + void unlock() { + if ( LOCK.isHeldByCurrentThread() ) + LOCK.unlock(); } /** @@ -170,10 +130,22 @@ class ReLock implements SyLock { Condition newCondition() { return LOCK.newCondition(); } /** - * 检查锁是否被占用 + * {@inheritDoc} * - * @return 是否被占用 + * @return {@inheritDoc} */ + @Override public boolean isLocked() { return LOCK.isLocked(); } + + /** + * {@inheritDoc} + * + * @return {@inheritDoc} + * + * @since 0.1.1 + */ + @Override + public + boolean isLockedCurrentThread() { return LOCK.isHeldByCurrentThread(); } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/lock/package-info.java b/src/main/java/fybug/nulll/pdconcurrent/lock/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..e2f659b613543c9adfaa092f1f003f6ec0deebbd --- /dev/null +++ b/src/main/java/fybug/nulll/pdconcurrent/lock/package-info.java @@ -0,0 +1,8 @@ +/** + *

各种锁的实现包.

+ * + * @author fybug + * @version 0.0.1 + * @since PDConcurrent 0.1.2 + */ +package fybug.nulll.pdconcurrent.lock; \ No newline at end of file diff --git a/src/main/java/fybug/nulll/pdconcurrent/package-info.java b/src/main/java/fybug/nulll/pdconcurrent/package-info.java index b3e8496e22213573e910b257d77636e4dd9b46a3..bcd81f6be4c25d43de5dcef4982a99802c4e0583 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/package-info.java +++ b/src/main/java/fybug/nulll/pdconcurrent/package-info.java @@ -5,7 +5,7 @@ * 附带{@code try***}的功能接口包{@link fybug.nulll.pdconcurrent.fun},在java原有的功能接口的基础上允许抛出异常 * * @author fybug - * @version 0.1.1 + * @version 0.1.2 * @since JDK 23+ */ package fybug.nulll.pdconcurrent; \ No newline at end of file