synchronized ("XXX".trim().intern()) {//锁内代码}
我在小测试中main跑多个不同线程不同代码下,这个锁是能起效的。
但是IDEA和AI都说这块写法会有问题,
我生产环境是webSocket下用的,比较难测,想问下会不会有问题(没锁住)
使用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关键字。
总之,不推荐在生产环境直接使用字符串作为锁对象,以免出现同步失效的问题。