通过自旋自定义一个分布式锁
1、定义锁类
package com.xiangwen.day3;
import java.util.concurrent.atomic.AtomicBoolean;
public class MyReentLock {
private static AtomicBoolean atomicBoolean = new AtomicBoolean(false);
private static String currentClient = "default";
public static void tryLock(long waitTime, String clientUuid) throws InterruptedException {
long start = System.currentTimeMillis();
while (true) {
if (atomicBoolean.compareAndSet(false, true)) {
currentClient = clientUuid;
break;
} else {
long end = System.currentTimeMillis();
if ((end - start) >= waitTime) {
System.out.println("超过最大等待时间了"+(end-start));
break;
}
}
}
}
public static void unLock(String uuid) {
if (currentClient.equals(uuid)) {
atomicBoolean.compareAndSet(true, false);
}
}
}
2、测试类
package com.xiangwen.day3;
import java.util.UUID;
public class MyReentLockClientToTest {
private static int ticket = 50;
public static void main(String[] args) {
//模拟100个客户端去远程调用,调用会传送客户端uuid
for (int i = 0; i < 100; i++) {
new Thread(() -> {
long start=System.currentTimeMillis();
String uuid = UUID.randomUUID().toString();
try {
MyReentLock.tryLock(20000, uuid);
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread() + "剩余票数" + (--ticket));
} else {
System.out.println("票卖光了");
}
MyReentLock.unLock(uuid);
} catch (Exception e) {
e.printStackTrace();
}
long end=System.currentTimeMillis();
System.out.println(Thread.currentThread()+"耗时"+(end-start));
}).start();
}
}
}
运行截图



结论:总耗时是15100ms,虽然有50个线程模拟正常卖票逻辑每次消耗100ms,本来应该是50*100,但实际因为有线程休眠,用户态和内核态切换消多消耗了200ms,实际每次耗时平均是300多ms,然后最终是300*50=1500ms
如果按照下面换成自旋,50个工作线程每个节省100ms,实际节省了5秒,能发现线程任务刚开始很慢,后来越来越快,看到线程标号能发现,当前面任务结束后,后面用的线程看着是复用的之前的线程



浙公网安备 33010602011771号