同步锁相关
大约 1 分钟
关于单体项目在控制并发方面代码编写要注意的问题
之前也犯过类似的错误,所以更需要注意,先观察以下代码:
/**
* 生成用户文档
*/
public void generateUserDoc(String uid) {
User user = userMapper.selectById(uid);
if (user == null) {
return; // 找不到用户就不处理了。
}
synchronized(uid) {
// xxx 同步处理业务逻辑
}
}
在这段代码中,我们通常会认为,只要是同一个人的生成文档需求,则排队处理,因为锁对象是String
且字符串对象值都是相同的uid
。 但是,在真实环境下,虽然都同为值相同的uid,但是其在堆中的地址却可能不一样。只要 obj a != obj b
, 哪怕 obj a equals obj b
,也不会产生同步效果
就好比
String a = new String("Hello");
String b = new String("Hello");
a.equals(b); // true
a == b; // false
在使用字符串的前提下,可以用以下工具来解决问题
注意哈,这个工具还在@Beta版本。此工具来源于Google的Guava工具包
private static Interner<String> lock = Interners.newWeakInterner();
public <T> HandleResult<T> handle(String uid) {
try {
// 单线程处理用户消息
synchronized (lock.intern(uid)) {
// xxx 业务逻辑
}
} catch (Exception e) {
log.error("", e);
}
return HandleResult.success();
}