課本閱讀 6小時
整理筆記 3小時html
課本閱讀 7小時
整理筆記 5小時程序員
一、併發:邏輯控制流在時間上重疊
二、併發程序:使用應用級併發的應用程序稱爲併發程序。
三、三種基本的構造併發程序的方法:編程
(1)進程,用內核來調用和維護,有獨立的虛擬地址空間,顯式的進程間通訊機制。
(2)I/O多路複用,應用程序在一個進程的上下文中顯式的調度控制流。邏輯流被模型化爲狀態機。
(3)線程,運行在一個單一進程上下文中的邏輯流。由內核進行調度,共享同一個虛擬地址空間。安全
一、構造併發服務器的天然方法就是,在父進程中接受客戶端鏈接請求,而後建立一個新的子進程來爲每一個新客戶端提供服務。
二、由於父子進程中的已鏈接描述符都指向同一個文件表表項,因此父進程關閉它的已鏈接描述符的拷貝是相當重要的,並且由此引發的存儲器泄露將最終消耗盡可用的存儲器,使系統崩潰。服務器
基於進程的併發echo服務器的重點內容網絡
(1)須要一個SIGCHLD處理程序,來回收僵死子進程的資源。
(2)父子進程必須關閉各自的connfd拷貝。對父進程尤其重要,以免存儲器泄露。
(3)套接字的文件表表項中的引用計數,直到父子進程的connfd都關閉了,到客戶端的鏈接纔會終止。多線程
注意:進程的模型:共享文件表,但不是共享用戶地址空間。 優勢:一個進程不可能不當心覆蓋兩一個進程的虛擬存儲器。
缺點:獨立的地址空間使得進程共享狀態信息變得更加困難。進程控制和IPC的開銷很高。併發
Unix IPC是指全部容許進程和同一臺主機上其餘進程進行通訊的技術,包括管道、先進先出(FIFO)、系統V共享存儲器,以及系統V信號量。函數
一、echo服務器必須響應兩個相互獨立的I/O時間:
(1)網絡客戶端發起鏈接請求(2)用戶在鍵盤上鍵入命令行。
二、I/O多路複用技術的基本思路:使用select函數,要求內核掛起進程,只有在一個或多個I/O事件發生後,纔將控制返回給應用程序。
三、將描述符集合當作是n位位向量:b(n-1),……b1,b0
每一個位bk對應於描述符k,當期僅當bk=1,描述符k才代表是描述符集合的一個元素。能夠作如下三件事:
(1)分配它們;(2)將一個此種類型的變量賦值給另外一個變量;(3)用FDZERO、FDSET、FDCLR和FDISSET宏指令來修改和檢查它們。
四、echo函數:未來自科幻段的每一行回送回去,直到客戶端關閉這個連接。學習
一、狀態機就是一組狀態、輸入事件和轉移,轉移就是將狀態和輸入時間映射到狀態,自循環是同一輸入和輸出狀態之間的轉移。
事件驅動器的設計優勢:
(1)比基於進程的設計給了程序員更多的對程序行爲的控制
(2)運行在單一進程上下文中,所以,每一個邏輯流都能訪問該進程的所有地址空間,使得流之間共享數據變得很容易。
(3)不須要進程上下文切換來調度新的流。
缺點:
(1)編碼複雜
(2)不能充分利用多核處理器
粒度:每一個邏輯流每一個時間片執行的指令數量。併發粒度就是讀一個完整的文本行所須要的指令數量。
一、線程:運行子啊進程上下文中的邏輯流。
二、線程有本身的線程上下文,包括一個惟一的整數線程ID、棧、棧指針、程序計數器、通用目的寄存器和條件碼。全部運行在一個進程裏的線程共享該進程的整個虛擬地址空間。
一、主線程:每一個進程開始生命週期時都是單一線程。
對等線程:某一時刻,主線程建立的對等線程
二、線程與進程的不一樣:
(1)線程的上下文切換要比進程的上下文切換快得多;
(2)和一個進程相關的線程組成一個對等池,獨立於其餘線程建立的線程。
(3)主線程和其餘線程的區別僅在於它老是進程中第一個運行的線程。
三、對等池的影響
(1)一個線程能夠殺死它的任何對等線程;
(2)等待它的任意對等線程終止;
(3)每一個對等線程都能讀寫相同的共享資源。
線程例程:線程的代碼和本地數據被封裝在一個線程例程中。每個線程例程都以一個通用指針做爲輸入,並返回一個通用指針。
pthread create函數建立一個新的線程,並帶着一個輸入變量arg,在新線程的上下文中運行線程例程f。新線程能夠經過調用pthread _self函數來得到本身的線程ID。
一個線程的終止方式:
(1)當頂層的線程例程返回時,線程會隱式的終止;
(2)經過調用pthread _exit函數,線程會顯示地終止。若是主線程調用pthread _exit,它會等待全部其餘對等線程終止,而後再終止主線程和整個進程。
pthread _join函數會阻塞,直到線程tid終止,回收已終止線程佔用的全部存儲器資源。pthread _join函數只能等待一個指定的線程終止。
一、在任何一個時間點上,線程是可結合的或者是分離的。一個可結合的線程可以被其餘線程收回其資源和殺死;一個可分離的線程是不能被其餘線程回收或殺死的。它的存儲器資源在它終止時有系統自動釋放。
二、默認狀況下,線程被建立成可結合的,爲了不存儲器漏洞,每一個可集合的線程都應該要麼被其餘進程顯式的回收,要麼經過調用pthread _detach函數被分離。
pthread _once函數容許初始化與線程例程相關的狀態。
once _control變量是一個全局或者靜態變量,老是被初始化爲PTHREAD _ONCE _INIT.
對等線程的賦值語句和主線程的accept語句之間引入了競爭。
一、每一個線程和其餘線程一塊兒共享進程上下文的剩餘部分。包括整個用戶虛擬地址空間,是由只讀文本、讀/寫數據、堆以及全部的共享庫代碼和數據區域組成的。線程也共享一樣的打開文件的集合。 二、任何線程均可以訪問共享虛擬存儲器的任意位置。寄存器是從不共享的,而虛擬存儲器老是共享的。
一、全局變量:虛擬存儲器的讀/寫區域只會包含每一個全局變量的一個實例。
二、本地自動變量:定義在函數內部但沒有static屬性的變量。
三、本地靜態變量:定義在函數內部並有static屬性的變量。
變量v是共享的,當且僅當它的一個實例被一個以上的線程引用。
一、共享變量引入了同步錯誤的可能性。
二、線程i的循環代碼分解爲五部分:
Hi:在循環頭部的指令塊
Li:加載共享變量cnt到寄存器%eax的指令,%eax表示線程i中的寄存器%eax的值
Ui:更新(增長)%eax的指令
Si:將%eaxi的更新值存回到共享變量cnt的指令
Ti:循環尾部的指令塊。
一、進度圖將指令執行模式化爲從一種狀態到另外一種狀態的轉換。轉換被表示爲一條從一點到相鄰點的有向邊。合法的轉換是向右或者向上。
二、臨界區:對於線程i,操做共享變量cnt內容的指令構成了一個臨界區。
三、互斥的訪問:確保每一個線程在執行它的臨界區中的指令時,擁有對共享變量的互斥的訪問。
四、安全軌跡線:繞開不安全區的軌跡線
不安全軌跡線:接觸到任何不安全區的軌跡線就叫作不安全軌跡線
五、任何安全軌跡線都能正確的更新共享計數器。
一、當有多個線程在等待同一個信號量時,你不能預測V操做要重啓哪個線程。
二、信號量不變性:一個正在運行的程序毫不能進入這樣一種狀態,也就是一個正確初始化了的信號量有一個負值。
一、二元信號量:將每一個共享變量與一個信號量s聯繫起來,而後用P(S)和V(s)操做將這種臨界區包圍起來,這種方式來保護共享變量的信號量。
二、互斥鎖:以提供互斥爲目的的二元信號量
加鎖:一個互斥鎖上執行P操做稱爲對互斥鎖加鎖,執行V操做稱爲對互斥鎖解鎖。對一個互斥鎖加了鎖但尚未解鎖的線程稱爲佔用了這個互斥鎖。
計數信號量:一個唄用做一組可用資源的計數器的信號量
一、信號量的做用:(1)提供互斥(2)調度對共享資源的訪問 二、生產者—消費者問題:生產者產生項目並把他們插入到一個有限的緩衝區中,消費者從緩衝區中取出這些項目,而後消費它們。
三、讀者—寫者問題:
(1)讀者優先,要求不讓讀者等待,除非已經把使用對象的權限賦予了一個寫者。
(2)寫者優先,要求一旦一個寫者準備好能夠寫,它就會盡量地完成它的寫操做。
(3)飢餓就是一個線程無限期地阻塞,沒法進展。
寫順序程序只有一條邏輯流,寫併發程序有多條併發流,並行程序是一個運行在多個處理器上的併發程序。並行程序的集合是併發程序集合的真子集。
一、線程安全:當且僅當被多個併發線程反覆地調用時,它會一直產生正確的結果。
線程不安全:若是一個函數不是線程安全的,就是線程不安全的。
二、線程不安全的類:
(1)不保護共享變量的函數
(2)保持跨越多個調用的狀態的函數。
(3)返回指向靜態變量的指針的函數。解決辦法:重寫函數和加鎖拷貝。
(4)調用線程不安全函數的函數。
一、可重入函數:當它們被多個線程調用時,不會引用任何共享數據。可重入函數是線程安全函數的一個真子集 。
二、關鍵思想是咱們用一個調用者傳遞進來的指針取代了靜態的next變量。
三、顯式可重入:沒有指針,沒有引用靜態或全局變量
隱式可重入:容許它們傳遞指針
四、可重入性即便調用者也是被調用者的屬性,並不僅是被調用者單獨的屬性。
一、競爭:當一個程序的正確性依賴於一個線程要在另外一個線程到達y點以前到達它的控制流中的x點時,就會發生競爭。
二、線程化的程序必須對任何可行的軌跡線都正確工做。
一、死鎖:一組線程被阻塞了,等待一個永遠也不會爲真的條件。
二、程序員使用P和V操做不當,以致於兩個信號量的禁止區域重疊。
三、重疊的禁止區域引發了一組稱爲死鎖區域的狀態。
四、死鎖是不可預測的。
一、教材:第十二章 二、課程資料:https://www.shiyanlou.com/courses/413 實驗樓實驗 三、學習指導:http://group.cnblogs.com/topic/73069.html