|
@@ -0,0 +1,128 @@
|
|
|
+package cn.com.qmth.stmms.biz.lock.impl;
|
|
|
+
|
|
|
+import java.util.concurrent.ExecutorService;
|
|
|
+import java.util.concurrent.Executors;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
+import java.util.function.IntUnaryOperator;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 简单读写锁实现<br>
|
|
|
+ * 0表示空闲状态,-1表示正在写,>0表示正在读
|
|
|
+ *
|
|
|
+ * @author luoshi
|
|
|
+ *
|
|
|
+ */
|
|
|
+public class ReadWriteLock {
|
|
|
+
|
|
|
+ private static ReadOperator readOperator = new ReadOperator();
|
|
|
+
|
|
|
+ private static UnReadOperator unreadOperator = new UnReadOperator();
|
|
|
+
|
|
|
+ private AtomicInteger value;
|
|
|
+
|
|
|
+ public ReadWriteLock() {
|
|
|
+ this.value = new AtomicInteger(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ public int read() {
|
|
|
+ int result = 0;
|
|
|
+ while ((result = value.updateAndGet(readOperator)) < 1) {
|
|
|
+ ;
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int unRead() {
|
|
|
+ return value.updateAndGet(unreadOperator);
|
|
|
+ }
|
|
|
+
|
|
|
+ public int readCount() {
|
|
|
+ return Math.max(0, value.get());
|
|
|
+ }
|
|
|
+
|
|
|
+ public int write() {
|
|
|
+ while (!value.compareAndSet(0, -1)) {
|
|
|
+ ;
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean tryWrite() {
|
|
|
+ return value.compareAndSet(0, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ public int unWrite() {
|
|
|
+ while (!value.compareAndSet(-1, 0)) {
|
|
|
+ ;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean writing() {
|
|
|
+ return value.get() == -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ static class ReadOperator implements IntUnaryOperator {
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int applyAsInt(int operand) {
|
|
|
+ return operand >= 0 ? operand + 1 : operand;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ static class UnReadOperator implements IntUnaryOperator {
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int applyAsInt(int operand) {
|
|
|
+ return operand >= 1 ? operand - 1 : operand;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ static class LockTestThread implements Runnable {
|
|
|
+
|
|
|
+ private ReadWriteLock lock;
|
|
|
+
|
|
|
+ private int number;
|
|
|
+
|
|
|
+ public LockTestThread(int number, ReadWriteLock lock) {
|
|
|
+ this.lock = lock;
|
|
|
+ this.number = number;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ for (int i = 0; i < 10000; i++) {
|
|
|
+ if (Math.random() < 0.7) {
|
|
|
+ System.out.println("thread " + number + " read:" + lock.read());
|
|
|
+ try {
|
|
|
+ Thread.sleep(100 * ((i % 10) + 1));
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ System.out.println("thread " + number + " unread:" + lock.unRead());
|
|
|
+ } else {
|
|
|
+ System.out.println("thread " + number + " write:" + lock.write());
|
|
|
+ try {
|
|
|
+ Thread.sleep(100 * ((i % 10) + 1));
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ System.out.println("thread " + number + " unwrite:" + lock.unWrite());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ ExecutorService executor = Executors.newFixedThreadPool(5);
|
|
|
+ final ReadWriteLock lock = new ReadWriteLock();
|
|
|
+ for (int i = 0; i < 5; i++) {
|
|
|
+ executor.submit(new LockTestThread(i + 1, lock));
|
|
|
+ }
|
|
|
+
|
|
|
+ executor.shutdown();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|