同步锁相关

YuJia大约 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();
}