尽量不要使用 synchronized(String a) 因为JVM中,字符串常量池具有缓存功能!,就会导致你会加锁在同一个对象。
public class StringProblem {
//使用字符串定义变量r1和r2,这样会使r1和r2指向常量池的同个数据,使得r1和r2实际上是一个对象
private static String r1 = "a";
private static String r2 = "a";
public static void main(String[] args) {
//1、定义线程A
new Thread(() -> {
//获得对象r1
synchronized (r1) {
System.out.println("获取资源1");
try {
//这里的目的主要是让线程A长期持有锁,这样线程B没法获取到锁,一直阻塞
while (true) {
System.out.println(Thread.currentThread().getName() + "执行中");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程A").start();
//2、定义线程B
new Thread(() -> {
synchronized (r2) {
while (true) {
System.out.println("获取资源2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "线程B").start();
}
}
返回结果
获取资源1
线程A执行中
线程A执行中
线程A执行中
线程A执行中
总结
由此可知,synchronized一般不要使用String对象作为锁,如果使用,一定要做好对象区分,否则就会导致对象一致的问题