前段时间讲了synchronized锁方法,锁this对象,锁非this对象。具体可以看往期的文章,今天我们来看下锁非this对象(锁String对象)的一个注意点。在Java中是有常量池缓存的功能的,就是说如果我先声明了一个String str1 = “a”; 再声明一个一样的字符串的时候,取值是从原地址去取的,也就是说是同一个对象。这也就导致了在锁字符串对象的时候,可以会取得意料之外的结果(字符串一样会取得相同锁),下面看一个例子介绍。
这里synchronized锁的是字符串对象,如果不是同一个对象,那么两个线程就可以异步进来。下面看下线程和测试结果。
这里建两个线程,线程B和线程A一样就不贴出来了,都是将“xc”字符串传给上面的测试方法。下面看下测试结果。
从结果可以就看到,线程B并没有进来,也就说明两个线程持有的是同一个锁,即字符串对象是同一个。这就是String常量池会带来的问题。所以在大多数情况下,同步代码块synchronized代码块不使用String作为锁对象,而采用其他。
这里将线程A和线程B传进来的参数用new方式创建对象。这样就可以保证不是同一个对象。从而打印的会是异步打印。
所以大家在使用字符串作为同步锁对象的时候要注意~~