【Java高併發學習】並行基礎概念

並行基礎概念

1.同步與異步

  1. 同步synchronous:方法一旦開始調用,調用者必須等到方法返回後,才能繼續後續的行爲。比如先做飯、後炒菜。
  2. 異步asynchronous:方法開始調用後,調用者可以進行後續操作,等待方法返回結果使用。比如做飯時進行炒菜動作。

2.併發與並行

2者都可以標識多個任務一起執行。
  1. 併發偏重於多個任務交替執行,但有可能是串行的。
  2. 並行即同時開始執行。

3.臨界區

表示一種公共資源或者共享數據,可以被多個線程來使用,但是每一次只能有一個線程使用。一旦被佔用,下一個使用者必須等待佔用結束。比如一臺打印機,在打印的A同時,後面的B必須等待前面的A結束。

4.阻塞和非阻塞

用來形容多線程間的相互影響。當一個線程佔用了臨界區的資源,那麼所有需要該資源的線程都必須在這個臨界區中等待。這樣導致線程掛起,進入阻塞狀態。非阻塞強調沒有線程妨礙其他線程執行。

5.死鎖、飢餓、活鎖

  1. 死鎖,即線程之間互相把持着對方需要的資源,無法進行後續執行陷入死鎖狀態。
  2. 飢餓,即某些線程一直無法獲取繼續執行下去的資源,導致程序無法執行。在線程優先級太低、某些線程一直佔據資源的情況下可能出現,這就需要特別的控制算法。
  3. 活鎖,當線程之間保持謙讓原則,則可能互相釋放自己的資源給對方使用,使得資源來回跳轉沒有任一線程獲取足夠資源,導致都無法繼續執行下去。

6.併發級別

  1. 阻塞
    阻塞線程在無法獲取足夠資源之前無法執行。使用synchronized、重入鎖在等待臨界區資源時該線程就爲阻塞掛起,直到獲取足夠資源爲止。
  2. 無飢餓
    線程之間存在優先級,則資源會優先滿足給優先級高的線程,那麼優先級低的線程容易進入飢餓。如果鎖是公平的,滿足先來後到,那麼就不會出現飢餓。
  3. 無障礙
    是一種最弱的非阻塞調度,線程之間不會因臨界區資源而被掛起。線程會一起進入臨界區,當存在數據競爭時,無障礙線程會回滾自己的操作,否則繼續執行直到結束。阻塞控制方式可以稱爲悲觀策略,一旦線程之間發生衝突,便以保護共享數據爲第一優先級。非阻塞可稱爲樂觀策略,認爲線程之間不會或者概率很小發生衝突;線程進行無障礙執行,但一旦發現衝突便應該回滾。可使用“一致性標記”來實現無障礙執行,操作前獲取、保存該標記,操作結束後再次獲取並檢查是否一致,一致則無衝突,否則反之需要回滾重新進行。
  4. 無鎖
    無鎖的並行是無障礙的,這時所有線程均能訪問臨界區,但是需保證必然有一個線程能夠在有限步內完成操作離開臨界區。
  5. 無等待
    要求所有線程均能在有限步內完成,而不引起飢餓問題。控制步驟上限也可分爲有界無等待、線程數無關的無等待。RCU(Read-Copy-Update)便是無等待的:對數據的讀不進行控制,但在寫數據時先獲取原始數據副本,只修改副本數據,之後在合適的時機回寫數據。

7.原子性

指一個操作是不可中斷的,即便多個線程一起執行,一個操作一旦開始就不會被其他線程干擾。比如一個static int變量,多個線程同時進行賦值,則賦值唯一不可中斷。但是long類型在32位系統下不是原子性的,因爲long有64位。

8.可見性

指當一個線程修改了某一個共享變量的值,其他線程是否能夠立即知道這個修改。緩存優化、硬件優化、指令重排、編輯器優化等都有可能導致可見性問題。

9.有序性

在同一個線程內,代碼是依次執行的。但在併發時,程序的執行可能會出現亂序,進行指令重排。指令重排保證串行語義一致,但在多線程間的語義一致沒有保證。
以下原則是指令重排無法違背的:
  1. 程序順序原則:一個線程內保證語義的串行性
  2. volatile規則:volatile變量的寫,先發生於讀,保證了volatile變量的可見性
  3. 鎖規則:解鎖必然發生在隨後的加鎖前,如果對一個鎖解鎖後,再加鎖,那麼加鎖的動作絕對不能重排到解鎖動作之前。否則無法獲得該鎖。
  4. 傳遞性:A先於B,B先於C,那麼A必然先於C
  5. 線程的star()方法先於它的每一個動作
  6. 線程的所有操作先於線程的終結(Thread.join())
  7. 線程的中斷(interrupt)先於被中斷線程的代碼
  8. 對象的構造函數執行、結束先於finalize()方法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章