You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

synchronized方法与特定资源锁:哪种实现更正确且性能更佳?

Java并发场景:synchronized方法 vs 特定资源加锁的正确性与性能对比

在Java并发场景中,使用synchronized方法(锁this)和针对特定资源加锁这两种方式,哪种实现更正确、性能更优?我的理解是,为需要避免并发修改的特定对象加锁效率更高,因为其他操作不同对象的线程可正常执行。


方式一:使用synchronized方法(锁this)

class Solution {

    public String getSessionKey(int user) {
        if (validateSessionKey(user)) {
            return someConcurrentHashMap.get(user).getKey();
        }
        throw new InvalidSessionException(SESSION_NOT_FOUND);
    }

    public synchronized String createSession(int user) {
        if (validateSessionKey(user)) {
            return someConcurrentHashMap.get(user).getKey();
        }
        UserSession session = new UserSession(user, generateSessionId(), LocalDateTime.now(ZoneOffset.UTC));
        someConcurrentHashMap.put(user, session);
        sessionKeyToUser.put(session.getKey(), user);
        return someConcurrentHashMap.get(user).getKey();
    }

    public int getUserBySessionKey(String sessionKey) {
        return sessionKeyToUser.getOrDefault(sessionKey, -1);
    }

}

方式二:针对特定资源加锁

class Solution {

    private final Object createSessionLock = new Object();

    public String getSessionKey(int user) {
        if (validateSessionKey(user)) {
            return someConcurrentHashMap.get(user).getKey();
        }
        throw new InvalidSessionException(SESSION_NOT_FOUND);
    }

    public String createSession(int user) {
        // 若用户已存在则锁用户对象,否则锁全局新建锁
        if (someConcurrentHashMap.containsKey(user)) {
            return createForExistingUser(user);
        }
        return createForNewUser(user);
    }


    public int getUserBySessionKey(String sessionKey) {
        return sessionKeyToUser.getOrDefault(sessionKey, -1);
    }

    private String createForExistingUser(int user) {
        if (validateSessionKey(user)) {
            return someConcurrentHashMap.get(user).getKey();
        }
        UserSession userSession = someConcurrentHashMap.get(user);
        synchronized (userSession) {
            if (validateSessionKey(user)) {
                return someConcurrentHashMap.get(user).getKey();
            }
            UserSession session = new UserSession(user, generateSessionId(), LocalDateTime.now(ZoneOffset.UTC));
            someConcurrentHashMap.put(user, session);
            sessionKeyToUser.put(session.getKey(), user);
            return someConcurrentHashMap.get(user).getKey();
        }
    }

    private String createForNewUser(int user) {
        if (validateSessionKey(user)) {
            return someConcurrentHashMap.get(user).getKey();
        }
        synchronized (createSessionLock) {
            if (validateSessionKey(user)) {
                return someConcurrentHashMap.get(user).getKey();
            }
            UserSession session = new UserSession(user, generateSessionId(), LocalDateTime.now(ZoneOffset.UTC));
            someConcurrentHashMap.put(user, session);
            sessionKeyToUser.put(session.getKey(), user);
            return someConcurrentHashMap.get(user).getKey();
        }
    }
}

正确性分析

  • synchronized方法(锁this):能保证线程安全,但锁粒度过大——整个Solution实例的所有synchronized方法都会互相阻塞,哪怕是操作不同用户的createSession请求,也会被串行执行,存在不必要的等待逻辑。
  • 特定资源加锁:采用细粒度锁+双重检查的设计,针对不同资源分别加锁,既保证了并发修改特定资源时的线程安全,又不会阻塞操作其他资源的线程,更贴合业务场景的正确性需求。需要注意:
    • 针对已存在用户加锁时,同步块内的二次检查能避免因会话对象被替换导致的锁失效问题;
    • 新建用户时使用全局锁,配合双重检查可防止多个线程重复创建同一用户的会话。

性能对比

你的理解完全正确,特定资源加锁的性能远优于synchronized方法:

  • synchronized方法锁粒度大,所有调用createSession的线程无论操作哪个用户都必须排队,高并发场景下会成为明显的性能瓶颈;
  • 特定资源加锁时,操作不同用户的线程可并行执行:比如线程A处理用户1的会话创建,线程B可同时处理用户2的会话创建,仅当多个线程操作同一用户(或同时创建新用户)时才会阻塞,大幅提升了并发吞吐量。

内容的提问来源于stack exchange,提问作者Sagar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:21:58