尽量不要使用 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对象作为锁,如果使用,一定要做好对象区分,否则就会导致对象一致的问题