java 中的同步方法问题

synchronized method issue in java

下面显示了三种不同的同步方法。

甲:

 public synchronized static int addCount1() {
        for (int i = 0; i < 10000; i++) {
            count++;
        }
        return count;
    }

乙:

static void addCount2() {
    synchronized (TestDoubleThread.class) {
        for (int i = 0; i < 10000; i++) {
            count++;
        }
    }
}

C:

void addCount3(String key) {
    synchronized (myMap.get(key)) {
        for (int i = 0; i < 10000; i++) {
            count++;
        }
    }
}

他们都可以按照我的预期进行同步。但是,我想知道哪个更好,以及它们之间的显着差异是什么。特别是对于案例 B 和案例 C。

这是我的完整代码:

public class TestDoubleThread extends Thread {

    String jobNmae;

    static int count = 0;

    TestDoubleThread(String jobName) {
        this.jobNmae = jobName;
    }

    public static void main(String[] args) throws Exception {

        TestDoubleThread t1 = new TestDoubleThread("A");
        TestDoubleThread t2 = new TestDoubleThread("B");
        t1.start();
        t2.start();

        Thread.sleep(3 * 1000L);
        System.out.println("count=" + TestDoubleThread.count);
    }

    public void run() {
        // addCount2();
        addCount3("A");
    }

    public synchronized static int addCount1() {
        for (int i = 0; i < 10000; i++) {
            count++;
        }
        return count;
    }

    static void addCount2() {
        synchronized (TestDoubleThread.class) {
            for (int i = 0; i < 10000; i++) {
                count++;
            }
        }
    }

    void addCount3(String key) {
        synchronized (myMap.get(key)) {
            for (int i = 0; i < 10000; i++) {
                count++;
            }
        }
    }

    public static java.util.Map<String, TestDoubleThread> myMap = new java.util.HashMap<String, TestDoubleThread>();
    static {
        myMap.put("A", new TestDoubleThread("A"));
        myMap.put("B", new TestDoubleThread("B"));
    }
}

addCount2TestDoubleThread.class 上同步,而 addCount3myMap.get(key) 返回的 TestDoubleThread 实例上同步。由于您使用 addCount3("A"); 执行它,因此两个线程在同一个对象上同步,因此一个必须等​​待另一个才能执行该方法。因此它的行为与 addCount2 完全相同,后者也在同一个对象上同步。

另一方面,如果将其更改为 addCount3(this.jobNmae),每个线程将在不同的对象上同步,因此两个线程将能够同时执行 addCount3,你的 count 会被搞砸的。