並發基礎之重要概念

  • 2019 年 10 月 5 日
  • 筆記

版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/qq_37933685/article/details/80850429

個人部落格:https://suveng.github.io/blog/​​​​​​​

並行計算基礎

為什麼需要並行

  • Linus Torvalds :並行計算只有在 影像處理 和 服務端編程 2個領域可以使用,並且它在這2個領域確實有著大量廣泛的使用。但是在其它任何地方,並行計算毫無建樹!

並行計算還出於業務模型的需要

  • 並不是為了提高系統性能,而是確實在業務上需要多個執行單元。
  • 比如HTTP伺服器,為每一個Socket連接新建一個處理執行緒
  • 讓不同執行緒承擔不同的業務工作
  • 簡化任務調度

幾個重要的概念

  • 同步(synchronous)和非同步(asynchronous)
  • 並發(Concurrency)和並行(Parallelism)
  • 臨界區
  • 阻塞(Blocking)和非阻塞(Non-Blocking)
  • 鎖(Deadlock)、飢餓(Starvation)和活鎖(Livelock)
  • 並行的級別

1.同步(synchronous)和非同步(asynchronous)

2.並發(Concurrency)和並行(Parallelism)

3.臨界區

臨界區用來表示一種公共資源或者說是共享數據,可以被多個執行緒使用。但是每一次,只能有一個執行緒 使用它,一旦臨界區資源被佔用,其他執行緒要想使用這個資源,就必須等待。

4.阻塞(Blocking)和非阻塞(Non-Blocking)

阻塞和非阻塞通常用來形容多執行緒間的相互影響。

比如一個執行緒佔用了臨界區資源,那麼其它所有需要 這個資源的執行緒就必須在這個臨界區中進行等待,等待會導致執行緒掛起。這種情況就是阻塞。此時,如果佔用資源的執行緒一直不願意釋放資源,那麼其它所有阻塞在這個臨界區上的執行緒都不能工作。

非阻塞允許多個執行緒同時進入臨界區

5.死鎖(Deadlock)、飢餓(Starvation)和活鎖(Livelock)

飢餓是指某一個或者多個執行緒因為種種原因無法獲得所需要的資源,導致一直無法執行.

6.並發級別

  1. 阻塞 當一個執行緒進入臨界區後,其他執行緒必須等待
  2. 非阻塞
    1. 無障礙 無障礙是一種最弱的非阻塞調度,自由出入臨界區,無競爭時,有限步內完成操作,有競爭時,回滾數據
    2. 無鎖 是無障礙的,保證有一個執行緒可以勝出
    3. 無等待 無鎖的,要求所有的執行緒都必須在有限步內完成,無飢餓的

有關並行的2個重要定律

Amdahl定律(阿姆達爾定律)

Amdahl定律(阿姆達爾定律) – 定義了串列系統並行化後的加速比的計算公式和理論上限 – 加速比定義:加速比=優化前系統耗時/優化後系統耗時

加速比= 優化前系統耗時/ 優化後系統耗時=500/400=1.25

結論:

增加CPU處理器的數量並不一定能起到有效的作用,提高系統內可並行化的模組比重,合理增加並行處理器數量才能以最小的投入,得到最大的加速比

Gustafson定律(古斯塔夫森)

說明處理器個數,串列比例和加速比之間的關係

結論:

只要有足夠的並行化,那麼加速比和CPU個數成正比

執行緒的基本操作

中斷執行緒

public void Thread.interrupt() // 中斷執行緒  public boolean Thread.isInterrupted() // 判斷是否被中斷  public static boolean Thread.interrupted() // 判斷是否被中斷,並清除當前中斷狀態

掛起(suspend)和繼續執行(resume)執行緒

– suspend()不會釋放鎖 – 如果加鎖發生在resume()之前 ,則死鎖發生

等待執行緒結束(join)和謙讓(yeild)

public final void join() throws InterruptedException  public final synchronized void join(long millis) throws InterruptedException  static void yield() 對調度程式的一個暗示,即當前執行緒願意產生當前使用的處理器。  

執行緒執行完畢後,系統會調用notifyAll();

不要在Thread實例上使用 wait()和notify()方法

守護執行緒

  1. 在後台默默地完成一些系統性的服務,比如垃圾回收執行緒、JIT執行緒就可以理解為守護執行緒
  2. 當一個Java應用內,只有守護執行緒時,Java虛擬機就會自然退出

執行緒優先順序

public final static int MIN_PRIORITY = 1;  public final static int NORM_PRIORITY = 5;  public final static int MAX_PRIORITY = 10;    Thread high=new HightPriority();  LowPriority low=new LowPriority();  high.setPriority(Thread.MAX_PRIORITY);  low.setPriority(Thread.MIN_PRIORITY);  low.start();  high.start();

基本的執行緒同步操作

synchronized

– 指定加鎖對象:對給定對象加鎖,進入同步程式碼前要獲得給定對象的鎖。 – 直接作用於實例方法:相當於對當前實例加鎖,進入同步程式碼前要獲得當前實例的鎖。 – 直接作用於靜態方法:相當於對當前類加鎖,進入同步程式碼前要獲得當前類的鎖。

Object.wait() Obejct.notify()