一、線程,進程,協程的區別? html
- 進程是 具備獨立功能的程序的一次運行活動,是 系統進行資源分配和調度的一個獨立單位。
- 線程是 進程的一個執行單元,是CPU執行的基本單位
- 一個進程能夠有多個線程,多個線程也能夠併發執行(單線程CPU 在同一時間內只可以運行一個線程,多核 CPU 能夠同時調度多個線程執行)
- 1)進程間相互獨立,同一進程的各線程間共享進程中的資源。某進程內的線程在其它進程不可見
2)調度和切換:線程上下文切換比進程上下文切換要快得多
3)線程不可以獨立執行,必須依存在進程中,由應用程序提供多個線程執行控制
- 能夠建立線程來異步處理一些計算,像Unity的Job System就可讓粒子、動畫、資源加載、場景加載等等放到Worker Threads中,利用多核特性對性能進行優化。
- 另外Unity還提供了協程來模擬多線程,將一個函數分紅多個部分來順序執行,本質是一個迭代器塊,仍是在主線程執行,用yield return返回
- GPU並行計算
線程執行開銷小,但不利於資源的管理和保護;而進程正相反。
二、哪些資源是進程共享的?
多個進程 能夠共享 進程代碼段data section、進程的公有數據(線程間通信)等系統資源,能夠調用同一段程序代碼
三、進程中的哪些資源是線程共享的?
線程私有
程序計數器 :每一個線程都有本身獨立的程序計數器,用來指示下一條指令的地址。
虛擬機棧:即棧區,在編譯期間完成分配。
線程共享
堆:垃圾收集器管理的主要區域。
方法區 :全部線程共享,存儲已被虛擬機加載的類信息,常量,靜態變量,即時編譯器編譯後的代碼等數據。這個區域的內存回收目標主要是針對常量池的對象的回收和對類型的卸載。
線程共享資源
|
線程獨享資源
|
地址空間 data section
|
程序計數器
|
全局變量 global
|
寄存器
|
打開的文件 file fd
|
棧
|
子進程
|
狀態字
|
鬧鈴
|
|
|
|
記帳信息 id
|
|
四、進程通訊方式
- 進程互斥與同步(PV)
- 信號signal 與 信號量semaphore
- 共享存儲器系統(共享存儲區)
- 消息傳遞系統(直接發送/信箱通訊)
- 管道通訊系統(共享文件)
- socket、文件鎖
全局變量則不是
管道是半雙工的,
是一種固定大小的緩衝區。當管道滿時,進程在寫管道會被阻塞,而當管道空時,進程讀管道會被阻塞
五、進程同步
在多道程序環境下,進程是併發執行的,不一樣進程之間存在着不一樣的相互制約關係(互斥和同步)。進程同步是對多個進程的執行順序進行協調
互斥:
爭用資源,指某一資源同時只容許一個訪問者對其進行訪問(沒法限制順序),經常使用 互斥信號量 記錄PV
互斥量 mutex
,至關於一把鎖,保證同類進程互斥
C#中的lock是互斥量,但用於線程間互斥
同步:一個進程在某一點等待另外一個進程提供信息,兩進程存在直接的制約關係 。同步實現訪問者對資源的有序訪問。在大多數狀況下,同步已經實現了互斥。少數狀況是指能夠容許多個訪問者同時訪問資源。
臨界資源 :一次僅容許一個進程使用的資源。
臨界區 :每一個進程中訪問臨界資源的那段程序代碼
信號量S(用於同步)
當它的值小於
0時,其絕對值表示等待使用該資源的進程個數。
信號量機制-PV操做
--wait ++signal 操做
信號量用於 進程間或線程間,生產者消費者問題等……
進程同步有哪幾種機制
- 原子操做:指不會被線程調度機制打斷的操做。這種操做一旦開始,就一直運行到結束,中間不會有任何context switch(切換到另外一個線程)
- 信號量機制:PV操做。必須有公共內存,不能用於分佈式操做系統,這是它最大的弱點。
- 自旋鎖: 調用者申請的資源若是被佔用,即自旋鎖被已經被別的執行單元保持,則調用者一直循環在那裏看是否該自旋鎖的保持着已經釋放了鎖(比較低級)
- 管程: 將共享變量和對它們的操做集中在一個模塊中,操做系統或併發程序就由這樣的模塊構成。模塊之間聯繫清晰,便於維護和修改,易於保證正確性
- 會合:進程間直接進行相互做用, 一個進程能夠調用另外一個進程的入口。先到達會合處的等待後到達者 +FCFS。分佈式系統可用。
- 分佈式系統: 網絡上的一組計算機造成的系統。參數全爲值參, 並且不可爲指針。
原子操做是不可分割的。在單處理器系統(UniProcessor)中,可以在單條指令中完成的操做均可以認爲是" 原子操做",由於中斷只能發生於指令之間
可是,在對稱多處理器(Symmetric Multi-Processor)中,因爲系統中有多個處理器在獨立地運行,即便能在單條指令中完成的操做也有可能受到干擾。咱們以decl (遞減指令)爲例,這是一個典型的"讀-改-寫"過程,涉及兩次內存訪問,CPU A、B各自存到本身的寄存器處理,最後寫入內存的結果可能就不正確(多核CPU通常一級緩存與二級緩存是每一個核心進行分別均衡分配的,三級緩存纔是多個核心一塊兒共享的 )
C++有atomic_flag,atomic<T>,atomic……略。除此以外的操做不保證是原子操做
對於指針強制類型轉換或者c++ placement new等狀況,可能沒法保證struct或class裏的成員不跨越cacheline
六、線程同步的方式有哪些?
- 臨界區(Critical Section): 在任意時刻只容許一個線程對共享資源進行訪問,經過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問。不能跨進程,只能實現線程互斥
- 互斥量:採用互斥對象機制,只有擁有互斥對象的線程纔有訪問公共資源的權限。由於互斥對象只有一個,因此能夠保證公共資源不會被多個線程同時訪問。
- 信號量:它容許同一時刻多個線程訪問同一資源,可是須要控制同一時刻訪問此資源的最大線程數量。
- 事件(信號):經過通知操做的方式來保持多線程同步,還能夠方便的實現多線程優先級的比較操做。
以上Event、Semaphore、Mutex 是內核對象,可以跨進程使用
七、什麼是死鎖
在兩個或者多個併發進程中,若是每一個進程
持有某種資源而又等待其它進程釋放它或它們如今保持着的資源,在未改變這種狀態以前都不能向前推動,稱這一組進程產生了死鎖。
死鎖產生的緣由
系統資源不足,進程推動順序不當
死鎖的4個必要條件 怎麼處理
- 互斥條件:資源互斥 一個資源一次只能被一個進程使用
- 請求與保持條件:佔有並等待 一個進程因請求資源而阻塞時,對已得到資源保持不放
- 不剝奪條件: 不可搶佔 進程得到的資源,在未徹底使用完以前,不能強行剝奪
- 循環等待條件:循環等待 若干進程之間造成一種頭尾相接的環形等待資源關係
處理死鎖的策略
1)預防死鎖: 破壞四個條件 資源靜態分配
2)避免死鎖: 如銀行家算法,而是在資源的動態分配過程當中,用某種方法去防止系統進入不安全狀態,從而避免發生死鎖。
3)檢測和解除死鎖:死鎖檢測算法
4)不處理:鴕鳥算法,用於當死鎖真正發生且影響系統正常運行時,才手動干預,從新啓動
安全狀態指存在安全序列。系統在進行資源分配以前,先計算資源分配的安全性,若這次分配會致使系統進入不安全狀態,則進程等待。
存在安全序列時,就可避免死鎖發生
系統進入不安全狀態(四個死鎖的必要條件同時發生)未必就會產生死鎖。固然,產生死鎖後,系統必定處於不安全狀態。
八、虛擬內存
32位機中,每一個進程最大2^32地址(由於指針4字節尋址),即4GB虛擬內存
將那些當前要運行的少數頁面或段先裝入內存即可運行,其他部分暫留在盤上。
當內存耗盡時,電腦會自動調用硬盤來充當內存,以緩解內存的緊張。 若計算機運行程序或操做所需的隨機存儲器(RAM)不足時,則Windows 會用虛擬存儲器進行補償。 它將計算機的RAM和硬盤上的臨時空間組合。 當RAM運行速率緩慢時,它便將數據從RAM移動到稱爲「分頁文件」的空間中。
虛擬存儲器是由硬件和操做系統自動實現存儲信息調度和管理的。它的工做過程包括6個步驟:
①中央處理器訪問主存的邏輯地址分解成組號a和組內地址b,並對組號a進行地址變換,即將邏輯組號a做爲索引,查地址變換表,以肯定該組信息是否存放在主存內。
②如該組號已在主存內,則轉而執行④;若是該組號不在主存內,則檢查主存中是否有空閒區,若是沒有,便將某個暫時不用的組調出送往輔存,以便將這組信息調入主存。
③從輔存讀出所要的組,並送到主存空閒區,而後將那個空閒的物理組號a和邏輯組號a登陸在地址變換表中。
④從地址變換表讀出與邏輯組號a對應的物理組號a。
⑤從物理組號a和組內字節地址b獲得物理地址。
⑥根據物理地址從主存中存取必要的信息。
若是程序要訪問的頁/段還沒有調入,那麼請求調入
若是內存已滿,則利用置換功能調出到盤上