1,什麼是併發?
在cpu角度講,多個cpu的核同時在工做。從Java的角度將,JVM在同一時刻在處理多個線程的請求。html
2,爲何要併發?
併發適用於多核處理器,以解決單線程阻塞致使效率低的問題,儘量利用cpu空閒等待時間。java
缺點:線程間的切換具備額外開銷。(用戶線程的上下文要複製到cpu線程上來執行)api
3,cpu、進程、線程的關係
cpu:執行計算機指令
操做系統的進程:程序的一次執行
操做系統的線程:操做系統調度器的調度的基本單位,交由cpu執行
cpu的線程:存放要執行的數據、指令等,是cpu的基本執行單位跨域
處理器的線程,與操做系統的進程,是 N:N 的關係。
操做系統的進程,與操做系統的線程,是1:N的關係。
因此,處理器線程與操做系統線程之間是 N:N 的關係。
一個進程至少有一個線程。線程不能跨域進程與訪問另外一個進程的內容。緩存
備註:
一般cpu的線程和核心數對應,幾核就是幾線程。可是單個線程並不能讓單個cpu核滿載形成cpu浪費,因而有了超線程技術,即一個cpu核負責兩個或多個線程的運行。安全
4,多線程的使用方式
多線程的使用有兩種:協同式和搶佔式。
協同式的實現比較簡單,因爲是在當前線程主動觸發其餘線程並等待結果返回,對調用者來講是能夠感知的,不存在線程安全問題。缺點是等待的過程是阻塞的,線程阻塞會形成必定程度的浪費性能。好比Lua。而Java採用搶佔式。多線程
5,多線程爭奪cpu使用權
cpu的基本調度單位是線程,由一個叫作「調度器(scheduler)」的操做系統的組件來調度。cpu的核會在一個 時間片 內執行用戶線程的操做。調度器會根據線程的優先級和線程的飢餓程度(等待時間)兩個因素來調度線程。併發
6,Java的線程與進程
jvm的線程與進程,是對操做系統的線程與進程的一種封裝,方便操做。jvm
jvm將操做系統的進程,封裝爲Process(抽象類),惟一實現類是ProcessImpl。有建立工具類ProcessBuilder。jvm對進程的封裝提供很是少的api,由於制定者不主張在java中以建立進程的方式執行多任務。函數
jvm將操做系統的線程,封裝爲Runable接口,java.lang包下有兩個實現類,Thread和Shutdown。Shutdown是用來執行JVM關閉的時候的鉤子函數的。普通代碼實際運行的時候,須要一個Thread類的對象來.start()來執行。這個.start()是一個synchronized方法,方法內部會調用native的.start0()交給操做執行。Thread類還提供不少native的方法來供調用。
java.concurrent包下有Callable接口,能夠有返回值(Future模式)。
7,線程的緩存與一致性規範
計算機的cpu的運算速度與內存的讀寫速度相差好幾個數量級,所以引入了高速緩存。每一個cpu的線程單獨配一個高速緩存。
帶來的問題:緩存一致性(CacheCoherence)。爲了解決緩存一致性的問題,要求各個處理器訪問緩存時遵循必定的協議(好比:MESI協議)。
Java虛擬機有本身的內存模型,虛擬機經過操做系統能夠操做cpu的線程和高速緩存,因此Java內存模型定義瞭如何解決緩存一致性的規範。
8,線程間的數據通信
協同式自然具有線程間的通信能力。Java採用搶佔式,線程只與主內存交互。若是線程間須要通信的話,須要先將數據從線程本身的工做內存寫回到主內存,另一個線程再從主內容加載到它的線程。
每個java線程擁有本身的工做內存,全部的java線程共用一個主內存。
方便理解:
主內存對應java堆中的對象實例數據部分,物理硬件的主內存。
工做內存對應虛擬機棧中的部分區域,程序運行時主要訪問讀寫的是工做內存。
這種理解是片面的不許確的,但剛接觸的時候比較容易理解一些。
參考資料: