即使我们在不同的线程中使用不同的锁,为什么值设置正确

Why is value set correctly even though we use different locks in different threads

即使我们在不同的线程中使用不同的锁,为什么 value 设置正确?

public class MyThread implements Runnable {
    static String a = "LOCK";
    static String b = "LOCK";
    int id;
    static int value = 0;

    MyThread(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        if (id == 0) {
            synchronized (a) {
                for (int i = 0; i < Main.N; i++)
                    value = value + 3;
            }
        } else {
            synchronized (b) {
                for (int i = 0; i < Main.N; i++)
                    value = value + 3;
            }
        }
    }
}

public class Main {
    static final int N = 100000;
    static int ITER = 100;

    public static void main(String[] args) {
        Thread threads[] = new Thread[2];
        boolean sw = true;
        for (int j = 0; j < ITER; j++) {
            MyThread.value = 0;
            for (int i = 0; i < 2; i++)
                threads[i] = new Thread(new MyThread(i));
            for (int i = 0; i < 2; i++)
                threads[i].start();
            for (int i = 0; i < 2; i++) {
                try {
                    threads[i].join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (MyThread.value != 2 * 3 * N) {
                System.out.println("i was different than " + 2 * 3 * N + ", it is " + MyThread.value);
                sw = false;
            }
        }
        if (sw)
            System.out.println("Something is strange");
    }
}

切勿将 String 用作锁,因为可能存在另一个 String 的相同实例,因为字符串池。

在你的例子中,你的两个 "LOCK" 字符串实际上是同一个对象。

Java 字符串文字被保留以节省内存。

你的两个 "LOCK" 字符串(因此你锁定的两个对象)实际上是同一个对象。

这就是(原因之一)为什么你永远不应该锁定原语。