【发布时间】:2016-08-12 06:00:33
【问题描述】:
要求只允许单个线程执行用户管理(创建/更新/导入)操作,但不允许多个线程同时为同一用户执行用户操作。例如,当线程 A 正在创建用户 A 时,线程 B 不能同时导入用户 A 或创建用户 A,但允许线程 B 导入用户 B。以下代码线程对于这些要求是否安全?
public class UserManagement {
ConcurrentHashMap<Integer, Lock> userLock = new ConcurrentHashMap<>();
public void createUser(User user, Integer userId) {
Lock lock = userLock.putIfAbsent(userId, new ReentrantLock());
try {
lock.lock();
//create user logic
} finally {
lock.unlock();
}
}
public void importUser(User user, Integer userId) {
Lock lock = userLock.putIfAbsent(userId, new ReentrantLock());
try {
lock.lock();
//import user logic
} finally {
lock.unlock();
}
}
public void updateUser(User user, Integer userId) {
Lock lock = userLock.putIfAbsent(userId, new ReentrantLock());
try {
lock.lock();
// update user logic
} finally {
lock.unlock();
}
}
}
【问题讨论】:
-
看起来是线程安全的,但是一个奇怪的设计。如果
User刚刚被创建,另一个线程怎么可能对它做些什么呢? -
我投票结束这个问题,因为它是一个代码审查请求
-
可以移至代码审查
-
库 Javadoc 说
lock.lock()可能会失败并引发异常。如果发生这种情况,您不想致电lock.unlock()。您的lock.lock()调用应出现在try关键字之前。 -
这三种方法中的每一种都会在每次调用时创建一个新的
ReentrantLock实例,无论是否需要。这是无害的,但它可能会导致一些开发人员在阅读您的代码时扬起眉毛。 ---- 当我进一步考虑时,看起来你的方式比做必要的额外工作来防止构建不必要的锁更干净(并且可能更快)。唯一的难题是如何阻止其他开发人员想要“修复”您的代码。也许您应该发起一场运动,将其命名为设计模式。
标签: java multithreading locking