各種程序員都工作在各自的程序抽象維度,如果我們發現解決一件事情比較難,也許是我們面對的抽象級別還不夠高,或者引入的間接程度不夠,本文以抽象角度來剖析并發編程。
一、機器和OS級別抽象
(1)馮諾伊曼模型
經典的順序化計算模型,貌似可以保證順序化一致性,但是沒有哪個現代的多處理架構會提供順序一致性,馮氏模型只是現代多處理器行為的模糊近似。
這個計算模型,指令或者命令列表改變內存變量直接契合命令編程泛型,它以顯式的算法為中心,這和聲明式編程泛型有區別。就并發編程來說,會顯著的引入時間概念和狀態依賴
所以所謂的函數式編程可以解決其中的部分問題。
(2)進程和線程
進程抽象運行的程序,是操作系統資源分配的基本單位,是資源cpu,內存,IO的綜合抽象。
線程是進程控制流的多重分支,它存在于進程里,是操作系統調度的基本單位,線程之間同步或者異步執行,共享進程的內存地址空間。
(3)并發與并行
并發,英文單詞是concurrent,是指邏輯上同時發生,有人做過比喻,要完成吃完三個饅頭的任務,一個人可以這個饅頭咬一口,那個饅頭咬一口,這樣交替進行,最后吃完三個饅頭,這就是并發,因為在三個饅頭上同時發生了吃的行為,如果只是吃完一個接著吃另一個,這就不是并發了,是排隊,三個饅頭如果分給三個人吃,這樣的任務完成形式叫并行,英文單詞是parallel.
回到計算機概念,并發應該是單CPU時代或者單核時代的說法,這個時候CPU要同時完成多任務,只能用時間片輪轉,在邏輯上同時發生,但在物理上是串行的。現在大多數計算機都是多核或者多CPU,那么現在的多任務執行方式就是物理上并行的。
為了從物理上支持并發編程,CPU提供了相應的特殊指令,比如原子化的讀改寫,比較并交換。
(4)平臺內存模型
在可共享內存的多處理器體系結構中,每個處理器都有它自己的緩存,并且周期性的與主存同步,為什么呢?因為處理器通過降低一致性來換取性能,這和CAP原理通過降低一致性來獲取伸縮性有點類似,所以大量的數據在CPU的寄存器中被計算,另外CPU和編譯器為了性能還會亂序執行,但是CPU會提供存儲關卡指令來保證存儲的同步,各種平臺的內存模型或者同步指令可能不同,所以這里必須介入對內存模型的抽象,JMM就是其中之一。
二、編程模型抽象
(1)基于線程模型
(2)基于Actor模型
(3)基于STM軟件事務內存
……
Java體系是一個基于線程模型的本質編程平臺,所以我們主要討論線程模型。
三、并發單元抽象
大多數并發應用程序都是圍繞執行任務進行管理的,任務是抽象,離散的工作單元,所以編寫并發程序,首要工作就是提取和分解并行任務。一旦任務被抽象出來,他們就可以交給并發編程平臺去執行,同時在任務抽象還有另一個重要抽象,那就是生命周期,一個任務的開始,結束,返回結果,都是生命周期中重要的階段。那么編程平臺必須提供有效安全的管理任務生命周期的API.
四、線程模型
線程模型是Java的本質模型,它無所不在,所以Java開發必須搞清楚底層線程調度細節,不搞清楚當然就會有struts1,struts2的原理搞不清楚的基本災難(比如在struts2的action中塞入狀態,把struts2的action配成單例)。
用線程來抽象并發編程,是比較低級別的抽象,所以難度就大一些,難度級別會根據我們的任務特點有以下幾個類別
(1)任務非常獨立,不共享,這是最理想的情況,編程壓力為0.
(2)共享數據,壓力開始增大,必須引入鎖,Volatile變量,問題有活躍度和性能危險。
(3)狀態依賴,壓力再度增大,這時候我們基本上都是求助jdk 提供的同步工具。
五、任務執行
任務是一個抽象體,如果被抽象了出來,下一步就是交給編程平臺去執行,在Java中,描述任務的一個基本接口是Runnable,可是這個抽象太有限了,它不能返回值和拋受檢查異常,所以Jdk5.0有另外一個高級抽象Callable.
任務的執行在Jdk中也是一個底級別的Thread,線程有好處,但是大量線程就有大大的壞處,所以如果任務量很多我們并不能就創建大量的線程去服務這些任務,那么Jdk5.0在任務執行上做了抽象,將任務和任務執行隔離在接口背后,這樣我們就可以引入比如線程池的技術來優化執行,優化線程的創建。
任務是有生命周期的,所以Jdk5.0提供了Future這個對象來描述對象的生命周期,通過這個future可以取到任務的結果甚至取消任務。
六、鎖
當然任務之間共享了數據,那么要保證數據的安全,必須提供一個鎖機制來協調狀態,鎖讓數據訪問原子,但是引入了串行化,降低了并發度,鎖是降低程序伸縮性的原罪,鎖是引入上下文切換的主要原罪,鎖是引入死鎖,活鎖,優先級倒置的絕對原罪,但是又不能沒有鎖,在Java中,鎖是一個對象,鎖提供原子和內存可見性,Volatile變量提供內存可見性不提供原子,原子變量提供可見性和原子,通過原子變量可以構建無鎖算法和無鎖數據結構,但是這需要高高手才可以辦到。