SpringBoot 中正确使用锁
错误示范
@GetMapping("/api/tt/{lock}")
public String lockTest4(@PathVariable String lock) {
synchronized (lock) {
return "Hello";
}
}
学synchronized
关键字的时候,还记得只要是同一把锁就可以锁住,但是在web
开发中通常会漏掉框架里的多线程, 你以为锁住了,实质上这段代码是这样的
ExecutorService threadPool = Executors.newFixedThreadPool(1000);
threadPool.execute(() -> {
xxxController.lockTest4("lockKey");
});
所以这种用法是错误的!
正确示范
private <T> T withLock(String lock, Supplier<T> runnable) {
String v = null;
try {
v = cacheMap.get(lock);
synchronized (v) {
return runnable.get();
}
} catch (ExecutionException e) {
e.printStackTrace();
}
throw new RuntimeException("请刷新后重试");
}
private static final LoadingCache<String, String> cacheMap = CacheBuilder.newBuilder()
.initialCapacity(20) // 初识容量
.maximumSize(500) // 最大容量
.removalListener(notification -> {
System.out.println("-----");
System.out.println(LocalDateTime.now() + " " + notification.getKey() + " " + notification.getValue() + " 被移除,原因:" + notification.getCause());
System.out.println("-----");
}).build(new CacheLoader<>() {
@Override
public String load(String key) throws Exception {
System.out.println("load: " + key + " " + LocalDateTime.now());
return UUID.randomUUID().toString().replaceAll("-", "");
}
});
@GetMapping("/api/tt/{lock}")
public String lockTest4(@PathVariable String lock) {
return withLock(lock, () -> {
return "hello";
});
}
更简单的正确用法
synchronized (lock.intern()) {
...
}
String
的 intern
方法会复用常量池里的对象,所以锁持有的对象是同一个,就不会出现并发操作了。
转载自:https://juejin.cn/post/6985157004616564743