在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

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

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

  • 我在同步代碼塊中修改了作為同步監(jiān)視器的字符串lock的值,希望得出的結(jié)果是異步的(就是多個(gè)線程能夠同時(shí)進(jìn)入synchronized代碼塊中),但結(jié)果卻是同步的.我認(rèn)為其他線程進(jìn)入的時(shí)候會(huì)檢測(cè)該常量是否被鎖,由于我已經(jīng)在剛才運(yùn)行的線程中更改了常量的值后,其他線程再進(jìn)入的時(shí)候發(fā)現(xiàn)修改后的常量沒(méi)有被鎖,應(yīng)該會(huì)進(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的是對(duì)象(即"lock"),而不是對(duì)象的引用。

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

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

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

2018年1月31日 12:09