《JAVA 併發編程實戰》 第一章:簡介

1、併發簡史

早期的計算機不包含操做系統,從頭至尾只執行一個程序,對於昂貴而且稀有的計算機資源來講是一種浪費。編程

操做系統的出現使得計算機能運行多個程序,而且不一樣的程序都在單獨的進程中運行:操做系統爲各個獨立執行的進程分配各類資源,包括內存。若是須要的話,在不一樣的進程之間能夠經過一些粗顆粒度的通訊機制來交換數據,包括:套接字、信號處理器、共享內存、信號量以及文件等。緩存

之因此在計算機中加入操做系統來實現多個程序的同時執行,主要是基於如下緣由:安全

  • 資源利用率:等待的同時能夠運行另外一個程序
  • 公平性:不是由一個程序從頭至尾
  • 便利性:更容易實現

串行編程模型的優點在於直觀性和簡單性,每次只作一件事情,作完以後再作另外一件。然而並不高效,例如在烤麪包的時候,能夠去進行其餘事情,直到麪包烤完,進行通知。但凡作事高效的人,總能在串行性和異步性之間找到合理的平衡,對於程序來講一樣如此。多線程

2、線程的優點

若是使用得當,線程能夠有效地額下降程序的開發和維護等成本,同時提高複雜應用程序的性能。線程可以將大部分的異步工做流轉換成串行工做流,所以能更好的模擬人類的工做方式和交互方式。此外,線程還能夠下降代碼的複雜度,使代碼更容易編寫、閱讀和維護。併發

2.1 發揮多處理器的強大能力

因爲基本的調度單位是線程,所以若是程序中只有一個線程,那麼最多同時只能在一個處理器上運行。 多線程能夠同時在多個處理器上執行。若是設計正確,多線程能夠經過提升資源利用率來提高系統的吞吐率。異步

2.2 建模的簡單性

完成單任務時,很簡單,只要把這件事作好就行。可是在完成多任務的時候,不只要把活幹好,還要考慮不一樣任務之間存在優先級和時間。post

2.3 異步事件的簡化處理

一部分線程接受客戶端請求,另外一部分處理器請求。若是是單線程程序的話,處理請求時會停頓致使接受請求阻塞,爲了不這個問題單線程程序必須使用非阻塞的I/O,這種I/O的複雜性要遠遠高於同步I/O。性能

3、線程帶來的風險

Java對線程的支持實際上是一把雙刃劍。雖然Java提供了相應的語言和庫,以及一種明確的跨平臺內存模型,可是同時提升了對開發人員的技術要求,由於在更多的程序中會使用線程。優化

3.1 安全性問題

線程的安全性多是很是複雜的,在沒有充足的狀況下,多個線程中的操做執行順序是不可預測的,甚至會產生奇怪的結果。如下的程序會產生一個整數值序列。操作系統

由於value++ 不是一個原子性的操做:①讀取value;②給value+1;③將值寫入value。
因爲運行時可能有多個線程同時執行了讀操做,他們寫入時就會發生衝突,從而影響到結果。

3.2 活躍性問題

開發併發模塊時,必定要注意線程安全性是不可破壞的。安全性不只對多線程很重要,對於單線程一樣重要。此外,線程還會致使一些在單線程程序中不會出現的問題,例如活躍性問題。

安全性的含義是「永遠不發生糟糕的事情」,而活躍性則關注另外一個目標:「某件正確的事情最終會發生」。當某個操做沒法繼續執行下去的時候,就會發生活躍性問題。

具體問題和解決方法可見第十章:避免活躍性危險

3.3 性能問題

與活躍性問題關係密切的是性能問題。活躍性意義着某件正確的事情最終會發生,可是不夠好,由於咱們一般但願正確的事情儘快發生。

性能問題包括多方面:

  • 服務時間過長
  • 響應不靈敏
  • 吞吐率太低
  • 資源消耗太高
  • 可伸縮性較低

在設計良好的併發程序中,線程能提升程序的性能,可是不管如何,線程總會帶來某種程度的運行開銷。在多線程中,當線程調度器臨時掛起活躍性線程並轉而運行另外一個線程的時候,會頻繁的出現上下文切換操做,帶來很大的開銷:保存和恢復執行上下文,丟失局部性,而且CPU時間將更多的花在線程調度而不是線程運行上。當線程共享數據時,必須使用同步機制,而這些機制每每會抑制某些編譯器優化,使得內存緩存區中的數據無效,以及增長共享內存總線的同步流量。

具體問題和解決方法可見第十一章:性能與可伸縮性

3.4 線程無處不在

相關文章
相關標籤/搜索