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

时间:2017-10-17 17:35:07

标签: java multithreading locks

为什么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");
    }
}

2 个答案:

答案 0 :(得分:3)

永远不要使用String作为锁,因为字符串池可能与其他String的实例相同。

在您的情况下,您的两个"LOCK"字符串实际上是同一个对象。

答案 1 :(得分:3)

实习Java字符串文字以节省内存。

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

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