一:String.intern()解决
比如需要锁住的商品id是Long id = 1000;
synchronized (id.toString().intern()){
//do...
}
造成的问题:
常量池有限,存储在hashtable中,数据多了之后,碰撞厉害,而且容易加重full gc负担 。
二: google的Interners解决
在类级别初始化** Interners.newWeakInterner()**
public class test{
private static Interner<String> lock = Interners.newWeakInterner();
public void test() {
synchronized (lock.intern(id.toString())){
//do...
}
}
}
总结:Interners内部基于ConcurrentHashMap实现,而且可以设置引用类型,不会加重full gc负担,但有一个问题就是如果gc回收了存储在Interners里面的String,那lock.intern(lock)可能也会返回不同的引用,总之,还是建议使用Interners,效率和内存使用率更高。
测试时可以使用System.identityHashCode()查看锁住对象的HashCode是不是一致,一致即不同线程需获取同一个对象锁才能访问,实现被锁住的代码块串行化运行。