线程的互斥与同步机制
同個人博客:http://tsundere-x.top/
一、互斥
為何需要引入互斥機制?
當多個線程對同一數(shù)據(jù)并發(fā)讀寫(至少有一個線程執(zhí)行寫操作)時,這種情形被稱為競爭。競爭會導致數(shù)據(jù)讀或寫的不確定性。而有時這種不確定性是不可容忍的。
如何實現(xiàn)互斥?
在并發(fā)程序設計中,通常使用鎖機制來實現(xiàn)互斥
1、由用戶標記必須原子執(zhí)行的代碼段,即使用synchronized關鍵字
2、給資源一把配有自動機制的鎖
【注意】:
Java將資源限定為引用型對象,并為每一對象自動配備一把鎖:鎖初始時處于打開狀態(tài)。synchronized標記的原子代碼段在訪問資源前,會自動檢測資源對象持有的鎖是否處于打開狀態(tài)。若是,則占用并同時將鎖置為鎖閉態(tài),并在該代碼段執(zhí)行完畢后。將鎖的狀態(tài)值為打開態(tài);若否,則持有該代碼的線程因等待資源占用而進入阻塞態(tài)。
? 只有對象才有鎖,對基本類型的數(shù)據(jù),無法實現(xiàn)線程的互斥訪問。
? 對于未使用synchronized標記的代碼,鎖機制不起作用。
? 無論正常結束還是異常退出,都將自動釋放鎖。
死鎖和活鎖
死鎖:就是多個線程對臨界資源的循環(huán)等待,使得這些線程均都無法獲得執(zhí)行。
例如:A,B,C三個線程分別占用D1、D2、D3三個臨界資源,A只有獲得B占用的資源D2,方能繼續(xù)運行;而B只有獲得C占用的資源D3,方能繼續(xù)運行;C只有獲得A占用的資源D1,方能繼續(xù)運行。這樣,A,B,C處在對資源的循環(huán)等待狀態(tài),均無法前進。
活鎖:也稱饑餓。就是某線程雖有執(zhí)行的資格,但由于某種原因總是得不到執(zhí)行。
例如:A,B,C三個線程循環(huán)訪問臨界資源D,但A,B的優(yōu)先級相同,但均高于C。由于Java的搶占式策略,C線程可能總得不到執(zhí)行。
二、同步
同步(Sync)
多個線程的運行滿足特定的節(jié)奏
所謂同步,就是發(fā)出一個功能調用時,在沒有得到結果之前,該調用就不返回或繼續(xù)執(zhí)行后續(xù)操作。
根據(jù)這個定義,Java中所有方法都是同步調用,應為必須要等到結果后才會繼續(xù)執(zhí)行。我們在說同步、異步的時候,一般而言是特指那些需要其他端協(xié)作或者需要一定時間完成的任務。
簡單來說,同步就是必須一件一件事做,等前一件做完了才能做下一件事。
異步(Async)
多個線程的運行相互獨立,彼此間無依賴性
異步與同步相對,當一個異步過程調用發(fā)出后,調用者在沒有得到結果之前,就可以繼續(xù)執(zhí)行后續(xù)操作。當這個調用完成后,一般通過狀態(tài)、通知和回調來通知調用者。對于異步調用,調用的返回并不受調用者控制。
舉個例子簡單說明下兩者的區(qū)別:
同步:火車站多個窗口賣火車票,假設A窗口當賣第288張時,在這個短暫的過程中,其他窗口都不能賣這張票,也不能繼續(xù)往下賣,必須這張票處理完其他窗口才能繼續(xù)賣票。直白點說就是當你看見程序里出現(xiàn)synchronized這個關鍵字,將任務鎖起來,當某個線程進來時,不能讓其他線程繼續(xù)進來,那就代表是同步了。
異步:當我們用手機下載某個視頻時,我們大多數(shù)人都不會一直等著這個視頻下載完,而是在下載的過程看看手機里的其他東西,比如用qq或者是微信聊聊天,這種的就是異步,你執(zhí)行你的,我執(zhí)行我的,互不干擾。比如上面賣火車票,如果多個窗口之間互不影響,我行我素,A窗口賣到第288張了,B窗口不管A窗口,自己也賣第288張票,那顯然會出錯了。
并發(fā)
在操作系統(tǒng)中,是指一個時間段中有幾個程序都處于已啟動運行到運行完畢之間,且這幾個程序都是在同一個處理機上運行。其中兩種并發(fā)關系分別是同步和互斥。
并行
在單處理器中多道程序設計系統(tǒng)中,進程被交替執(zhí)行,表現(xiàn)出一種并發(fā)的外部特種;在多處理器系統(tǒng)中,進程不僅可以交替執(zhí)行,而且可以重疊執(zhí)行。在多處理器上的程序才可實現(xiàn)并行處理。從而可知,并行是針對多處理器而言的。并行是同時發(fā)生的多個并發(fā)事件,具有并發(fā)的含義,但并發(fā)不一定并行,也亦是說并發(fā)事 件之間不一定要同一時刻發(fā)生。
Java的同步機制 = 存取共享資源的互斥機制 + 線程間的通信機制
用于線程通信的方法存在于Object類中,包括wait()、notify()、notifyAll()。wait()會暫停當前線程的執(zhí)行,并釋放所持有的鎖,進入等待狀態(tài);notify()操作將喚醒一個等待的線程;notifyAll()將喚醒所有等待的進程。
【注意】
wait()、notify()、notifyAll()都是final方法,不允許被重寫;這些方法只能直接或間接地用于臨界區(qū)中,否則,將會產生非法監(jiān)控鎖狀態(tài)異常。
總結
以上是生活随笔為你收集整理的线程的互斥与同步机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【计算机网络复习 数据链路层】3.4.4
- 下一篇: 计算机网络——TCP/IP参考模型和五层