鍍金池/ 問答/Java  Linux/ 在同步代碼塊中使用字符串作為同步監(jiān)視器,在代碼塊中修改字符串變量,為什么不是同步

在同步代碼塊中使用字符串作為同步監(jiān)視器,在代碼塊中修改字符串變量,為什么不是同步?

  • 我在同步代碼塊中修改了作為同步監(jiān)視器的字符串lock的值,希望得出的結(jié)果是異步的(就是多個線程能夠同時進(jìn)入synchronized代碼塊中),但結(jié)果卻是同步的.我認(rèn)為其他線程進(jìn)入的時候會檢測該常量是否被鎖,由于我已經(jīng)在剛才運行的線程中更改了常量的值后,其他線程再進(jìn)入的時候發(fā)現(xiàn)修改后的常量沒有被鎖,應(yīng)該會進(jìn)入,但卻發(fā)生了同步.求大神解答!!
package duixiangsuo;

public class ChangeLock {

    private String lock = "lock";
    private void method() {
        synchronized (lock) {
            try {
                System.out.println("當(dāng)前線程" + Thread.currentThread().getName() + "開始");
                lock = "123";
                Thread.sleep(2000);
                System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "結(jié)束");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        final ChangeLock str = new ChangeLock();
        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                str.method();
            }

        }, "t1");
        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                str.method();
            }

        }, "t2");
        Thread t3 = new Thread(new Runnable() {

            @Override
            public void run() {
                str.method();
            }

        }, "t3");
        t3.start();
        t1.start();
        //Thread.sleep(5000);
        t2.start();
    }
}
回答
編輯回答
離殤

synchronized的是對象(即"lock"),而不是對象的引用。

當(dāng)你同時啟動3個線程時,可能都synchronized到了"lock"。要想得到你的預(yù)期(即synchronized到不同的對象),可做兩點改動:

  1. String lock前加上volatile關(guān)鍵字,保證引用的改變對其他線程是可見的;
  2. synchronized (lock)前隨機等待若干毫秒,讓各線程不同時跑到synchronized,比如這樣:
    private AtomicInteger counter = new AtomicInteger(0);

    private void method() {
        Thread.sleep(counter.addAndGet(100)); // 這里還要catch一個InterruptedExxception
        synchronized (lock) {
            ...
        }
    }

2018年1月31日 12:09