钟爱有嘉 2023-06-07 15:40 采纳率: 58.3%
浏览 24

synchronized使用问题

synchronized ("XXX".trim().intern()) {//锁内代码}
我在小测试中main跑多个不同线程不同代码下,这个锁是能起效的。
但是IDEA和AI都说这块写法会有问题,
我生产环境是webSocket下用的,比较难测,想问下会不会有问题(没锁住)

  • 写回答

1条回答 默认 最新

  • IT论之程序员 2023-06-07 21:39
    关注
    
    使用String对象作为锁对象会有潜在的问题,因为JVM会对字符串进行优化,有可能导致不同的字符串对象共享同一个内存空间。
    在你的例子中,如果两个线程调用的字符串是"XXX""XXX ",由于trim()和intern()操作,这两个字符串实际上会指向同一个对象,导致锁失效。
    所以,使用字符串作为锁对象时,推荐使用如下方式:
    1. 使用字符串的hashCode()作为锁:
    java
    synchronized ( "XXX".hashCode()) { ... }
    2. 使用新的String对象作为锁:
    java
    String lockObj = new String("XXX");
    synchronized (lockObj) { ... }
    3. 不使用字符串,选择其他对象作为锁:
    java 
    Object lockObj = new Object();
    synchronized (lockObj) { ... }
    对于你的webSocket示例,我的建议是:
    1. 不要直接使用字符串作为锁
    2. 可以为每个WebSocket连接生成一个唯一的锁对象,然后所有的同步块针对这个锁对象进行同步。例如:
    java
    Object lockObj = new Object();
    webSocket.onConnect((session) -> {
        session.setLockObj(lockObj);  //为连接生成锁对象
    });
    
    //同步块使用这个锁对象
    synchronized (session.getLockObj()) { ... } 
    3. 也可以使用其他的同步机制,如ReentrantLock来代替synchronized关键字。
    总之,不推荐在生产环境直接使用字符串作为锁对象,以免出现同步失效的问题。
    
    
    评论

报告相同问题?

问题事件

  • 创建了问题 6月7日