String对象存在于常量池中,相同内容的String对象地址相同,为同一对象。因此如果使用String作为锁时,如果之前设置String对象锁的值与后面设置的锁对应的String对象值相同则会影响代码的执行,比如下面的例子:
public class TestStringLock {
String str1 = "abc";
String str2 = "abc";
private void m1() {
print1();
}
private void m2() {
print2();
}
private void print1() {
synchronized (str1) {
try {
while (true) {
System.out.println("currentThreadName : " + Thread.currentThread().getName());
Thread.sleep(1000);
}
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
private void print2() {
synchronized (str2) {
try {
while (true) {
System.out.println("currentThreadName : " + Thread.currentThread().getName());
Thread.sleep(1000);
}
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String[] args) {
TestStringLock t = new TestStringLock();
Thread t1 = new Thread(t::m1, "t1");
Thread t2 = new Thread(t::m2, "t2");
t1.start();
t2.start();
}
}
currentThreadName : t1
currentThreadName : t1
currentThreadName : t1
currentThreadName : t1
currentThreadName : t1
currentThreadName : t1
currentThreadName : t1
上面代码中线程t1一直占用str1这把锁,t2会占用str2这把锁,按照常理两个线程不应该会相互影响,但是由于两个String对象值是一样的,因此t2线程实际是拿不到执行print2()方法的锁,因此会一直打印t1。