同個人部落格:http://tsundere-x.top/
一、互斥
為何需要引入互斥機制?
當多個線程對同一資料并發讀寫(至少有一個線程執行寫操作)時,這種情形被稱為競争。競争會導緻資料讀或寫的不确定性。而有時這種不确定性是不可容忍的。
如何實作互斥?
在并發程式設計中,通常使用鎖機制來實作互斥
1、由使用者标記必須原子執行的代碼段,即使用synchronized關鍵字
2、給資源一把配有自動機制的鎖
【注意】:
Java将資源限定為引用型對象,并為每一對象自動配備一把鎖:鎖初始時處于打開狀态。synchronized标記的原子代碼段在通路資源前,會自動檢測資源對象持有的鎖是否處于打開狀态。若是,則占用并同時将鎖置為鎖閉态,并在該代碼段執行完畢後。将鎖的狀态值為打開态;若否,則持有該代碼的線程因等待資源占用而進入阻塞态。
• 隻有對象才有鎖,對基本類型的資料,無法實作線程的互斥通路。
• 對于未使用synchronized标記的代碼,鎖機制不起作用。
• 無論正常結束還是異常退出,都将自動釋放鎖。
死鎖和活鎖
死鎖:就是多個線程對臨界資源的循環等待,使得這些線程均都無法獲得執行。
例如:A,B,C三個線程分别占用D1、D2、D3三個臨界資源,A隻有獲得B占用的資源D2,方能繼續運作;而B隻有獲得C占用的資源D3,方能繼續運作;C隻有獲得A占用的資源D1,方能繼續運作。這樣,A,B,C處在對資源的循環等待狀态,均無法前進。
活鎖:也稱饑餓。就是某線程雖有執行的資格,但由于某種原因總是得不到執行。
例如:A,B,C三個線程循環通路臨界資源D,但A,B的優先級相同,但均高于C。由于Java的搶占式政策,C線程可能總得不到執行。
二、同步
同步(Sync)
多個線程的運作滿足特定的節奏
所謂同步,就是發出一個功能調用時,在沒有得到結果之前,該調用就不傳回或繼續執行後續操作。
根據這個定義,Java中所有方法都是同步調用,應為必須要等到結果後才會繼續執行。我們在說同步、異步的時候,一般而言是特指那些需要其他端協作或者需要一定時間完成的任務。
簡單來說,同步就是必須一件一件事做,等前一件做完了才能做下一件事。
異步(Async)
多個線程的運作互相獨立,彼此間無依賴性
異步與同步相對,當一個異步過程調用發出後,調用者在沒有得到結果之前,就可以繼續執行後續操作。當這個調用完成後,一般通過狀态、通知和回調來通知調用者。對于異步調用,調用的傳回并不受調用者控制。
舉個例子簡單說明下兩者的差別:
同步:火車站多個視窗賣火車票,假設A視窗當賣第288張時,在這個短暫的過程中,其他視窗都不能賣這張票,也不能繼續往下賣,必須這張票處理完其他視窗才能繼續賣票。直白點說就是當你看見程式裡出現synchronized這個關鍵字,将任務鎖起來,當某個線程進來時,不能讓其他線程繼續進來,那就代表是同步了。
異步:當我們用手機下載下傳某個視訊時,我們大多數人都不會一直等着這個視訊下載下傳完,而是在下載下傳的過程看看手機裡的其他東西,比如用qq或者是微信聊聊天,這種的就是異步,你執行你的,我執行我的,互不幹擾。比如上面賣火車票,如果多個視窗之間互不影響,我行我素,A視窗賣到第288張了,B視窗不管A視窗,自己也賣第288張票,那顯然會出錯了。
并發
在作業系統中,是指一個時間段中有幾個程式都處于已啟動運作到運作完畢之間,且這幾個程式都是在同一個處理機上運作。其中兩種并發關系分别是同步和互斥。
并行
在單處理器中多道程式設計系統中,程序被交替執行,表現出一種并發的外部特種;在多處理器系統中,程序不僅可以交替執行,而且可以重疊執行。在多處理器上的程式才可實作并行處理。進而可知,并行是針對多處理器而言的。并行是同時發生的多個并發事件,具有并發的含義,但并發不一定并行,也亦是說并發事 件之間不一定要同一時刻發生。
Java的同步機制 = 存取共享資源的互斥機制 + 線程間的通信機制
用于線程通信的方法存在于Object類中,包括wait()、notify()、notifyAll()。wait()會暫停目前線程的執行,并釋放所持有的鎖,進入等待狀态;notify()操作将喚醒一個等待的線程;notifyAll()将喚醒所有等待的程序。
【注意】
wait()、notify()、notifyAll()都是final方法,不允許被重寫;這些方法隻能直接或間接地用于臨界區中,否則,将會産生非法監控鎖狀态異常。