为什么说synchronized一般不要使用String对象作为锁

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