Java併發模型(一)

學習資料來自http://ifeve.com/java-concurrency-thread-directory/java

1、多線程數據庫

  1. 進程和線程的區別: 一個程序運行至少一個進程,一個進程至少包含一個線程。
  2. 多線程: 多線程使得在一個程序內部可以擁有多個線程並行執行,一個線程的執行能夠被認爲是一個cpu在執行該程序,當一個程序運行在多線程下,就好像有多個CPU在同時執行該程序。

多線程在同一個程序內部併發執行,所以會對相同的內存空間進行併發讀寫操做。編程

思考: 服務器

  1. 若是一個線程在讀一個內存時,另外一個線程正向該內存進行寫操做,那麼進行讀操做的線程將得到什麼結果呢?是寫操做以前的舊值?仍是寫操做成功以後的新值?或者一半新一半舊的值?
  2. 若是兩個線程同是寫一個內存,在操做完成以後又是什麼結果呢?是第一個線程寫入的值?仍是第二個線程寫入的值?仍是兩個線程共同寫入的一個混合值?

 

2、多線程的優勢數據結構

1、資源利用率更好多線程

           好比CPU在等待磁盤讀取的時間很是空閒,能夠利用這一段時間去作一些其餘的事情。併發

2、程序設計在某些狀況下更簡單負載均衡

           好比單線程去操做兩個文件的讀取和處理,須要記錄每一個文件的讀取和處理狀態。相反,若是用兩個線程分別處理一個文件,一個線程在讀取的時候就會阻塞另外一個線程,此時,被阻塞的線程就能夠去執行處理的操做。不但提高磁盤和CPU利用率,編程也更加容易實現。異步

3、程序響應更快分佈式

           例如服務器在某一個端口監聽進來的請求,當一個請求到來時它去處理這個請求,處理完了再返回去監聽其餘請求。假設這個請求須要佔用大量的時間呢?

           另外一種方式是服務器監聽線程把進來的請求傳遞給工做者線程,而後立刻返回去監聽,這樣就可以接受和處理更多客戶端發送過來的請求,服務的響應也更快了。

3、多線程的代價

         1、設計更復雜

         通常來講,多線程應用程序比單線程應用程序更加複雜,在多線程訪問共享數據的時候,線程之間的交互每每很是複雜,不正確的線程同步產生的錯誤很是難以被發現,而且重現以修復。

         2、上下文切換的開銷

         當CPU執行一個線程切換到執行另一個線程的時候,它須要先存儲當前線程的本地數據、程序指針等,而後載入另外一個線程的本地數據、程序指針等,最後纔開始執行。這種切換叫作上下文切換(context switch),CPU會在一個上下文(context)中執行一個線程,而後切換到另外一個上下文(context)執行另一個線程。

         若是沒有必要應該儘可能減小上下文的切換。

         3、增長資源消耗

         除了CPU,線程還須要一些內存來維持它本地的堆棧,也須要佔用操做系統中一些資源來管理線程。咱們能夠寫一個程序建立100個線程,而後這些線程只是等待什麼都不作,而後看看佔用了多少內存。

4、併發編程模型

         併發編程模型指定了系統中的多線程如何經過協做來完成分配給它們的做業,不一樣的併發模型採用不一樣的方式拆分做業,同時線程間的協做和交互方式也不相同。

一、 併發模型與分佈式系統之間的類似性

併發模理相似於分佈式系統中使用的不少體系結構,在分佈式系統中進程之間能夠

通訊(進程可能在不一樣的機器中),在併發系統中線程之間也能夠相互通訊。例如爲工做者們(線程)分配做業的模型通常與分佈式系統中的負載均衡系統比較類似。

二、 並行工做者

委託者將傳入的做業被分配給不一樣的工做者上,每一個工做者完成整個任務,工做者們運做在不一樣的線程上,甚至可能在不一樣的CPU上。

 

優勢:容易理解,只須要添加更多的工做者來提升系統的並行度。

缺點:

  1. 併發工做者一般須要訪問一些共享數據,不管是內存中仍是數據庫中,一旦涉及到共享狀態狀況就會變得複雜。線程須要以某種方式存取共享數據,以確保某個線程的修改可以對其餘線程可見。線程須要避免竟態、死鎖以及不少其餘共享狀態的併發問題。

等待訪問共享數據時,線程之間的互相等待會丟失部分並行性,許多併發數據結構是阻塞的,意味着在某個時刻只有一個或者不多的線程能訪問,致使共享數據出現競爭狀態,出現必定串行化。

  1. 無狀態的工做者: 共享狀態可以被其餘線程修改,因此工做者在每次須要的時候必須重讀狀態,以確保每次都能訪問到最新的副本。工做者沒法在內部保存這個狀態稱爲無狀態的。特別是狀態保存在外部數據庫中的時候,每次重讀會致使速度變慢。
  2. 任務順序是不肯定的: 做業A可能在做業B以前就被分配工做者了,可是做業B反而有可能在做業A以前執行,也就是沒法保證哪一個做業最早或者最後被執行。

 

三、  流水線模型

也叫反應器系統、事件驅動系統或者無共享模型。

 

相似於工廠生產線上的工人們,每一個工做者只負責做業中的部分工做,當完成了本身這部分工做就轉發給下一個工做者,每一個工做者在本身的線程中運行,並不會和其餘工做者共享狀態。

在實際中可能會有多個不一樣的虛擬流水線同時動做,現實多是這樣的狀況。

 

Actors和Channels

Actors模型中每一個工做者都被稱爲actor。Actor之間能夠直接異步地發送和處理消息,actor能夠用來實現一個或多個前面描述的那種做業處理流水線。

 

Channel模型中,工做都之間不直接進行通訊。相返,它們在不一樣的通道中發佈本身的消息(事件)。其餘工做者能夠在這些通道上監聽消息,發送者無需知道誰在監聽。

 

流水線模型的優勢:

  1. 無需共享的狀態
  2. 有狀態的工做者
  3. 較好的硬件整合
  4. 合理的做業順序

流水線模型的缺點:

  1. 做業執行每每分佈到多個工做者上,並所以分佈到項目中的多個類上。這樣致使在追蹤某個做業到底被什麼代碼執行時變得困難。
  2. 加大了代碼編寫的難度,有時工做者的代碼須要寫成回調處理的形式。若在代碼中嵌入過多的回調處理,每每會出現所謂的回調地獄(callback hell)現像。

四、  函數式執行(Functional Parallelism)

函數式並行的基本思想是採用函數調用實現程序,函數被看做是代理人(agents)或者actor, 函數之間能夠像流水線模型(AKA反應器或者事件驅動系統)那樣互相發送消息。

         思考:使用哪一種併發模型好呢?

         一般狀況下,這個答案取決於你的系統打算作什麼。若是你的做業自己就是並行的、獨立的而且沒有必要共享狀態,你可能會使用並行工做者模型去實現你的系統。

         不少做業都不是天然並行和獨立的,對於這種類型的系統,使用流水線併發模型可以更好的發揮它的優點,並且比並行工做者模型更有優點。

相關文章
相關標籤/搜索