Java線程同步操作

synchronized

作用于對象實例:對給定對象加鎖,進(jìn)入同步代碼前要獲得給定對象的鎖。

作用于實例方法:相當(dāng)于對當(dāng)前實例加鎖,進(jìn)入同步代碼前要獲得當(dāng)前實例的鎖。

作用于靜態(tài)方法:相當(dāng)于對當(dāng)前類加鎖,進(jìn)入同步代碼前要獲得當(dāng)前類的鎖。

使用

給實例對象加鎖

public class AccountingSync implements Runnable {
    static AccountingSync instance = new AccountingSync();
    static int i = 0;

    @Override
    public void run() {
        for (int k = 0; k < 10000; k++) {
            synchronized (instance) {
                i++;
            }
        }
    }

    @Test
    public void testInteger() throws InterruptedException {
        int count = 10;
        Thread[] ts = new Thread[count];

        for (int k = 0; k < count; k++) {
            ts[k] = new Thread(instance);
        }

        // start
        for (int k = 0; k < count; k++) {
            ts[k].start();
        }

        // join
        for (int k = 0; k < count; k++) {
            ts[k].join();
        }

        System.out.println(i);
    }
}

給類方法加鎖

public class AccountingSync2 implements Runnable {
    static AccountingSync2 instance = new AccountingSync2();
    static int i = 0;

    public synchronized void increase() {
        i++;
    }

    @Override
    public void run() {
        for (int k = 0; k < 10000; k++) {
            increase();
        }
    }

    @Test
    public void testInteger() throws InterruptedException {
        int count = 10;
        Thread[] ts = new Thread[count];

        for (int k = 0; k < count; k++) {
            ts[k] = new Thread(instance);
        }

        // start
        for (int k = 0; k < count; k++) {
            ts[k].start();
        }

        // join
        for (int k = 0; k < count; k++) {
            ts[k].join();
        }

        System.out.println(i);
    }
}

給類方法加鎖的錯誤演示

public class AccountingSyncBad implements Runnable {
    static int i = 0;

    public synchronized void increase() {
        i++;
    }

    @Override
    public void run() {
        for (int k = 0; k < 10000; k++) {
            increase();
        }
    }

    @Test
    public void testInteger() throws InterruptedException {
        int count = 10;
        Thread[] ts = new Thread[count];

        for (int k = 0; k < count; k++) {
            ts[k] = new Thread(new AccountingSyncBad());
        }

        // start
        for (int k = 0; k < count; k++) {
            ts[k].start();
        }

        // join
        for (int k = 0; k < count; k++) {
            ts[k].join();
        }

        System.out.println(i);
    }
}

假設(shè)把給類實例加鎖中的每個實例比作一個門,上面的測試方法中每個門都有鎖但是10個門10把鎖,每個線程進(jìn)一個門。還是不能保證臨界區(qū)資源i同時只一個線程訪問

fix

@Test
public void testIntegerFix() throws InterruptedException {
  int count = 10;
  AccountingSyncBad instance = new AccountingSyncBad();
  Thread[] ts = new Thread[count];

  for (int k = 0; k < count; k++) {
    ts[k] = new Thread(instance);
  }

  // start
  for (int k = 0; k < count; k++) {
    ts[k].start();
  }

  // join
  for (int k = 0; k < count; k++) {
    ts[k].join();
  }

  System.out.println(i);
}

給靜態(tài)類方法加鎖

public class AccountingSyncClass implements Runnable {
    static int i = 0;

    public static synchronized void increase() {
        i++;
    }

    @Override
    public void run() {
        for (int k = 0; k < 10000; k++) {
            increase();
        }
    }

    @Test
    public void testInteger() throws InterruptedException {
        int count = 10;
        Thread[] ts = new Thread[count];

        for (int k = 0; k < count; k++) {
            ts[k] = new Thread(new AccountingSyncClass());
        }

        // start
        for (int k = 0; k < count; k++) {
            ts[k].start();
        }

        // join
        for (int k = 0; k < count; k++) {
            ts[k].join();
        }

        System.out.println(i);
    }
    
    @Test
    public void testIntegerFix() throws InterruptedException {
        int count = 10;
        AccountingSyncClass instance = new AccountingSyncClass();
        Thread[] ts = new Thread[count];

        for (int k = 0; k < count; k++) {
            ts[k] = new Thread(instance);
        }

        // start
        for (int k = 0; k < count; k++) {
            ts[k].start();
        }

        // join
        for (int k = 0; k < count; k++) {
            ts[k].join();
        }

        System.out.println(i);
    }
}

上面測試的testInteger方法和testIntegerFix方法都能得到正確的結(jié)果,原因是給靜態(tài)類方法加鎖相當(dāng)于10個門用的同一把鎖,保證了同一時間只有一個線程能訪問臨界區(qū)資源i。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,755評論 11 349
  • 本文出自 Eddy Wiki ,轉(zhuǎn)載請注明出處:http://eddy.wiki/interview-java.h...
    eddy_wiki閱讀 2,297評論 0 14
  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,886評論 0 11
  • 這是一篇聽課總結(jié)。 腦神經(jīng)最新研究發(fā)現(xiàn),想象的時候大腦經(jīng)歷著相同的過程。梵高想象畫布上畫的樣子,愛因斯坦想象引力波...
    海星_love閱讀 245評論 0 0
  • 文:藍(lán)玫汐 自古學(xué)生分等級,學(xué)神者,學(xué)霸者,學(xué)渣者,學(xué)沫者。 眼下,又多了個詞,叫“學(xué)婊”,專指那些看起來不努力,...
    藍(lán)玫汐閱讀 2,348評論 2 1

友情鏈接更多精彩內(nèi)容