1. 程式人生 > >併發程式設計裡面常見的概念

併發程式設計裡面常見的概念

1.同步和非同步的區別?
答:
同步互動:指傳送一個請求,需要等待返回,然後才能夠傳送下一個請求,有個等待過程;

非同步互動:指傳送一個請求,不需要等待返回,隨時可以再發送下一個請求,即不需要等待。 區別:一個需要等待,一個不需要等待,在部分情況下,我們的專案開發中都會優先選擇不需要等待的非同步互動方式。

2.併發和並行的區別?
答:舉例說明:
你吃飯吃到一半,電話來了,你一直到吃完了以後才去接,這就說明你不支援併發也不支援並行。

你吃飯吃到一半,電話來了,你停了下來接了電話,接完後繼續吃飯,這說明你支援併發。 (不一定是同時的

你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支援並行。(所以嚴格意義上來說,並行才是同時的


併發的關鍵是你有處理多個任務的能力,不一定要同時。
並行的關鍵是你有同時處理多個任務的能力。
所以我認為它們最關鍵的點就是:是否是『同時』。

在這裡插入圖片描述

3.死鎖、飢餓和活鎖的概念?
答:
死鎖:通俗地說,死鎖是兩個或者多個執行緒,相互佔用對方需要的資源,而都不進行釋放,導致彼此之間都相互等待對方釋放資源,產生了無限制等待的現象,死鎖一旦發生,如果沒有外力介入,這種等待將永遠存在,從而對程式產生嚴重的影響
飢餓:某一個或者多個執行緒因為種種原因無法獲得所需要的資源,導致一直無法執行,比如它的執行緒優先順序可能太低,而高優先順序的執行緒不斷搶佔它需要的資源,導致低優先順序執行緒無法工作。與死鎖相比,飢餓還是有可能在未來一段時間內解決的,比如高優先順序的執行緒已經完成任務,不再瘋狂地執行
在這裡插入圖片描述


活鎖:執行緒A和B都需要過橋(都需要使用程序),而都禮讓不走(那到的系統優先順序相同,都認為不是自己優先順序高),就這麼僵持下去.(很紳士,互相謙讓)
在這裡插入圖片描述

4.無鎖
無鎖的並行都是無障礙的。在無鎖的情況下,所有的執行緒都能嘗試對臨界區進行訪問,但不同的是,無鎖的併發保證必然有一個執行緒能夠在有限步內完成操作離開臨界區。
在無鎖的呼叫中,一個典型的特點是可能會包含一個無窮迴圈。在這個迴圈中,執行緒會不斷嘗試修改共享變數。如果沒有衝突,修改成功,那麼程式退出,否則繼續嘗試修改。但無論如何,無鎖的並行總能保證有一個執行緒是可以勝出的,不至於全軍覆沒。至於臨界區中競爭失敗的執行緒,它們則必須不斷重試,直到自己獲勝。如果運氣很不好,總是嘗試不成功,則會出現類似飢餓的現象,執行緒會停止不前。

下面就是一段無鎖的示意程式碼,如果修改不成功,那麼迴圈永遠不會停止。
在這裡插入圖片描述

5.執行緒的狀態
在這裡插入圖片描述
在這裡插入圖片描述

wait()與sleep()的區別,簡單來說wait()會釋放物件鎖而sleep()不會釋放物件鎖。這些問題有很多的資料,不再贅述。
初看起來wait() 和 notify() 方法與suspend()和 resume()
方法對沒有什麼分別,但是事實上它們是截然不同的。區別的核心在於,前面敘述的suspend()及其它所有方法線上程阻塞時都不會釋放佔用的鎖(如果佔用了的話),而wait()
和 notify() 這一對方法則相反。
如果另外的一個執行緒呼叫了相同物件的notifyAll()方法,那麼處於該物件的等待池中的執行緒就會全部進入該物件的鎖池中,準備爭奪鎖的擁有權。如果另外的一個執行緒呼叫了相同物件的notify()方法,那麼僅僅有一個處於該物件的等待池中的執行緒(隨機)會進入該物件的鎖池.

6.Thread.stop()方法是如何造成資料不一致的?
答:Thread.stop()方法在結束執行緒時,會直接終止執行緒,並且會立即釋放這個執行緒所持有的鎖。而這些鎖恰恰是用來維持物件一致性的。如果此時,寫執行緒寫入資料正寫到一半,並強行終止,那麼物件就會被寫壞,同時,由於鎖已經被釋放,另外一個等待該鎖的讀執行緒就順理成章的讀到了這個不一致的物件,悲劇也就此發生。