1. 程式人生 > >阻塞和非阻塞

阻塞和非阻塞

在介紹阻塞和非阻塞之前,我們先來了解一下多執行緒間一個重要的概念——臨界區。
臨界區——一種公有的資源或者共享資料,它可以被多個執行緒使用。臨界區資源一次只能被一個執行緒使用,其它執行緒必須等待上一個執行緒 執行完成之後,才能使用。臨界區資源是多執行緒之間重要保護物件,當臨界區資源同時被多個執行緒訪問時,容易出現錯誤。 程式碼示例:

  
/**
 * @author php
 * @date 2018/7/2
 */
public class CriticalRegion {
    //定義1000元
    public static Integer money = 1000;

    public static void main(String[] args) throws 
InterruptedException { //定義公共資源 CriticalRegion criticalRegion = new CriticalRegion(); //定義10個執行緒來購物 ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executorService.execute(() -> { criticalRegion
.shop(); }); } Thread.sleep(1000); System.out.println("最終還有:" + CriticalRegion.money); executorService.shutdown(); } //我們每次購物使用100塊錢 public void shop() { money = money - 100; System.out.println("使用了100元,我還有:" + CriticalRegion.money);
} }

執行結果:從中可以看出,多個執行緒,同時操作臨界區資源時,容易導致操作資源錯誤。在大部分情況下,這是一個很嚴重的問題。 大家可以多執行幾次,看看結果有什麼不同。


現在,我們修改一下shop()方法,在方法上加上sychronized。執行結果:sychronized可以讓臨界區資源,一次只能被一個執行緒訪問,

從而結果正確。


臨界區資源,在使用多執行緒時,要格外的注意,以免結果千奇百怪。
在我們瞭解臨界區之後,再來了解阻塞和非阻塞的概念。
阻塞和非阻塞通常被用來形容多執行緒間的相互影響。當一個執行緒佔用了臨界區資源,那麼其它需要使用這個資源的執行緒都必須在這個臨界區上等待。等待會導致執行緒掛起,這樣就形成了阻塞。如果佔用資源的執行緒一直沒有釋放資源,那麼其它的執行緒在這個臨界區上都不能繼續工作。
相反,非阻塞表明多個執行緒之間的執行是不會相互影響的。
通常,我們使用synchronized關鍵字,ReentrantLock(重入鎖)時,我們得到的執行緒就是阻塞執行緒。阻塞執行緒在執行程式碼前,都會嘗試得到臨界區資源的鎖,如果得不到,執行緒就會一直掛起,直到臨界區資源釋放。