第十章 進程間的通信 之 多線程基礎(一)

(一)多線程基礎知識

1、線程

(1)定義

一個基本的CPU執行單元 & 程序執行流的最小單元,比進程更小的可獨立運行的基本單位,可理解爲:輕量級進程
組成:線程ID + 程序計數器 + 寄存器集合 + 堆棧
注:線程自己不擁有系統資源,與其他線程共享進程所擁有的全部資源。

(2)作用

減少程序在併發執行時所付出的時空開銷,提高操作系統的併發性能。
爲什麼有了線程還要有進程?
進程的缺陷:

  1. 進程只能在一個時間幹一件事,如果想同時幹兩件事或多件事,進程就無能爲力了。
  2. 進程在執行的過程中如果阻塞,例如等待輸入,整個進程就會掛起,即使進程中有些工作不依賴於輸入的數據,也將無法執行。

進程屬於在處理器這一層上提供的抽象;線程則屬於在進程這個層次上再提供了一層併發的抽象。線程用於提高進程的併發度。
進程和線程的主要差別在於它們是不同的操作系統資源管理方式:
進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。
線程是進程的一個實體, 是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。
一個線程可以創建和撤銷另一個線程,同一個進程中的多個線程之間可以併發執行。

(3)狀態及狀態轉換

在這裏插入圖片描述

(4)分類

4.1)守護線程
守護用戶線程的線程,即在程序運行時爲其他線程提供一種通用服務,如垃圾回收線程

//設置該線程爲守護線程
thread.setDaemon(true);

4.2)非守護線程(用戶線程)
a.主線程(UI線程)
Android系統在程序啓動時會自動啓動一條主線程,用於處理四大組件與用戶進行交互的事情(如UI、界面交互相關)
注:因爲用戶隨時會與界面發生交互,因此主線程任何時候都必須保持很高的響應速度,所以主線程不允許進行耗時操作,否則會出現ANR
b.子線程(工作線程)
用戶手動創建的線程,用於處理耗時的操作(網絡請求、I/O操作等)
4.3)守護線程 & 非守護線程的區別
區別:虛擬機是否已退出:
當所有用戶線程結束時,因爲沒有守護的必要,所以守護線程也會終止,虛擬機也同樣退出;反過來,只要任何用戶線程還在運行,守護線程就不會終止,虛擬機就不會退出。守護線程不屬於不可或缺的存在。

(5)優先級

5.1)表示
線程優先級分爲10個級別,分別用Thread類常量表示。

Thread.MIN_PRIORITY // 優先級1
Thread.MAX_PRIORITY // 優先級10

5.2)設置
通過方法setPriority(int grade)進行優先級設置
默認線程優先級是5,即 Thread.NORM_PRIORITY

2、多線程

2.1)定義

多線程
一個程序(進程)運行時產生多個線程(任務)同時進行。
多線程目的
提高CPU資源的利用率,包括以下三點:

  1. 避免阻塞(異步調用)
    單個線程中的程序,是順序執行的。如果前面的操作發生了阻塞,那麼就會影響到後面的操作。
  2. 避免CPU空轉
    如果服務器只用單線程,即處理完一條HTTP請求,再處理下一條請求的話,CPU會存在大量的閒置時間。因爲處理一條請求,經常涉及到RPC、數據庫訪問、磁盤IO等操作,這些操作的速度比CPU慢很多,而在等待這些響應的時候,CPU卻不能去處理新的請求,其餘的請求只能一直處於等待狀態,因此服務器的性能就很差
  3. 提升性能
    多線程可以同時執行多個任務,對於可併發執行的任務而言,確實提高了性能。

並行與併發
並行:多個cpu實例或者多臺機器同時執行一段處理邏輯,是真正的同時。
併發:通過cpu調度算法,讓用戶看上去同時執行,實際上從cpu操作層面不是真正的同時。
其實,多線程本質是併發執行程序。因爲計算機任何特定時刻只能執行一個任務;多線程只是一種錯覺:只是因爲JVM快速調度資源來輪換線程,使得線程不斷輪流執行,所以看起來好像在同時執行多個任務而已(異步執行)
線程安全
一段代碼是線程安全的是指:在併發的情況之下,該代碼經過多線程使用,線程的調度順序不影響任何結果。這個時候使用多線程,我們只需要關注系統的內存,cpu是不是夠用即可。反過來,線程不安全就意味着線程的調度順序會影響最終結果,如不加事務的轉賬代碼:

void transferMoney(User from, User to, float amount){
    to.setMoney(to.getBalance() + amount);
    from.setMoney(from.getBalance() - amount);
}

如果線程不安全,則程序執行的結果並不是我們想要的結果,甚至有可能會導致實際場景嚴重的安全問題。
同步與異步
同步:發送一個請求,等待返回,然後再發送下一個請求;同步可以避免出現死鎖,讀髒數據的發生,可以保證安全性。
異步:發送一個請求,不等待返回,隨時可以再發送下一個請求;異步則是可以提高效率,可以併發執行多項工作。
Java中的同步指的是通過人爲的控制和調度,保證共享資源的多線程訪問成爲線程安全,來保證結果的準確。如上面的代碼簡單加入@synchronized關鍵字。

2.2)Android多線程編程兩大原則

(1)多線程編程兩大原則
1、不要阻塞UI線程(即主線程):單線程會導致主線程阻塞,然後出現ANR錯誤:主線程被阻塞超過5s則會出現錯誤
2、不要在UI線程之外更新UI組件
(2)解決方案——1個主線程+n個工作線程
1、將耗時任務放在工作線程中執行
2、將更新UI組件放在主線程中執行

2.3)實現方式

在這裏插入圖片描述

2.4)線程調度

(1)調度方式
1、當系統存在大量線程時,系統會通過時間片輪轉的方式調度線程,因此線程不可能做到絕對的併發
2、處於就緒狀態(Runnable)的線程都會進入到線程隊列中等待CPU資源(同一時刻在線程隊列中可能有很多個)
3、在採用時間片的系統中,每個線程都有機會獲得CPU的資源以便進行自身的線程操作;當線程使用CPU資源的時間到後,即時線程沒有完成自己的全部操作,JVM也會中斷當前線程的執行,把CPU資源的使用權切換給下一個隊列中等待的線程。(被中斷的線程將等待CPU資源的下一次輪迴,然後從中斷處繼續執行)
(2)調度優先級
Java虛擬機(JVM)中的線程調度器負責管理線程,並根據以下規則進行調度:
1、根據線程優先級(高-低),將CPU資源分配給各線程
2、具備相同優先級的線程以輪流的方式獲取CPU資源

2.5)線程同步

1、定義
當線程A使用同步方法A時,其他線程必須等到線程A使用完同步方法A後才能使用
2、同步方法用關鍵字 Synchronized 進行修飾

public synchronized void Sb_Android(){
        }

3、死鎖
(3.1)死鎖的四個必要條件

  • 互斥:每個資源要麼已經分配給了一個進程,要麼就是可用的。
  • 佔有和等待:已經得到了某個資源的進程可以再請求新的資源。
  • 不可搶佔:已經分配給一個進程的資源不能強制性地被搶佔,它只能被佔有它的進程顯式地釋放。
  • 環路等待:有兩個或者兩個以上的進程組成一條環路,該環路中的每個進程都在等待下一個進程所佔有的資源。

(3.2)死鎖的處理方法

  • 鴕鳥策略
  • 死鎖檢測與死鎖恢復
  • 死鎖預防
  • 死鎖避免

(3.3)鴕鳥策略
把頭埋在沙子裏,假裝根本沒發生問題。
因爲解決死鎖問題的代價很高,因此鴕鳥策略這種不採取任務措施的方案會獲得更高的性能。當發生死鎖時不會對用戶造成多大影響,或發生死鎖的概率很低,可以採用鴕鳥策略。
大多數操作系統,包括 Unix,Linux 和 Windows,處理死鎖問題的辦法僅僅是忽略它。
(3.4)死鎖的檢測與死鎖恢復

  1. 死鎖的檢測——資源分配圖
    每種類型一個資源的死鎖檢測算法是通過檢測有向圖是否存在環來實現,從一個節點出發進行深度優先搜索,對訪問過的節點進行標記,如果訪問了已經標記的節點,就表示有向圖存在環,也就是檢測到死鎖的發生。
  2. 死鎖的恢復
  • 利用搶佔恢復
  • 利用回滾恢復
  • 通過殺死進程恢復

(3.5)死鎖的預防
在程序運行之前預防發生死鎖。

  1. 破壞互斥條件
    例如假脫機打印機技術允許若干個進程同時輸出,唯一真正請求物理打印機的進程是打印機守護進程。
  2. 破壞佔有和等待條件
    一種實現方式是規定所有進程在開始執行前請求所需要的全部資源。
  3. 破壞不可搶佔條件
  4. 破壞環路等待
    給資源統一編號,進程只能按編號順序來請求資源。

(3.6)死鎖的避免

  1. 安全狀態
    如果沒有死鎖發生,並且即使所有進程突然請求對資源的最大需求,也仍然存在某種調度次序能夠使得每一個進程運行完畢,則稱該狀態是安全的。
  2. 銀行家算法
    算法要做的是判斷對請求的滿足是否會進入不安全狀態,如果是,就拒絕請求;否則予以分配。

2.6)線程聯合

線程A在佔有CPU資源期間,通過調用join()方法中斷自身線程執行,然後運行聯合它的線程B,直到線程B執行完畢後線程A再重新排隊等待CPU資源,這個過程稱爲線程A聯合線程B

3、進程

3.1)定義

是進程實體的運行過程 & 系統進行資源分配和調度的一個獨立單位

3.2)作用

使多個程序可 併發執行,以提高系統的資源利用率和吞吐量

3.3)狀態及狀態轉換

在這裏插入圖片描述
在這裏插入圖片描述

3.4)線程與進程區別

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章