使用String 的 intern做锁提高并发能力

时间:2020-11-24 19:09:13

一个场景:

某段代码只对同一个ip过来的请求同步处理:

  比如ip为a的请求进入了同步代码块,那么后续的ip为a的请求则在代码块外边等着,这时来了一个ip为b的请求,那么这个请求也可以进去,也就是a的所有请求们是同步处理的,b的所有请求也是同步处理的,但是a和b互相不影响。

一般可能会这样写代码:

String ip = 从请求中获取的ip;
synchronized(ip){

  ......  

}

这样写是不对的,因为我们并不能保证ip都是指向常量池中的,换句话说我们不能保证这个ip是同一个对象

这里有个小技巧上面的代码只要改成

synchronized(从请求中获取的ip.intern()){
......
}

就能保证锁对象唯一了,每次都是去常量池中取的对象。

假如某个ip长时间没有访问,那么常量池中该ip对应的对象可能会被清理掉,这个也不用怕,下次的访问又会在常量池中创建一个对象,后续的请求还是会拿这个对象作为进入此方法的条件。

那么有没有可能某个ip的请求已经进了代码了,这个ip的常量对象忽然被垃圾回收了呢?然后导致后续的同ip请求又在常量池中创建了一个新的对象?这个也不用担心,既然被当成了锁,那么在锁被打开之前不会被垃圾回收的