前言
這是一個長篇部落格,希望大家關注我並且一起學習java高併發
廢話不多說,直接開始
並行和併發
並行:多個執行緒同時處理多個任務
併發:多個執行緒處理同個任務,不一定要同時
下面用圖來描述並行和併發的區別:
(實現和虛線表示兩個不同的執行緒)
臨界區
是受保護的資源,可以被多個執行緒使用,但是每次只能有一個執行緒可以使用它
死鎖,飢餓,活鎖
死鎖
因為有些資源的彼此交叉使用,大家都阻塞了執行緒,所有關於這個資源的執行緒全部無法工作
飢餓
一個資源被高優先順序別的執行緒不斷搶佔著,導致低優先順序的執行緒無法工作
某一個執行緒一致佔著資源不放,導致需要這個資源的執行緒無法正常工作
活鎖
多個執行緒都主動將資源釋放給他人使用,就會出現資源不斷在兩個執行緒中跳動,而沒有一個執行緒可以正常執行
JMM(java記憶體模型)
在並行程式中,就是int i =1都變得及其複雜
下面來看下JMM的三個特性
- 原子性
和資料庫的原子性一樣,是指一個操作是不可中斷的,即使是在多個執行緒一起執行的時候,一個操作一旦開始,就不會被其它執行緒干擾
- 可見性
當一個執行緒修改了某個共享的值,其它執行緒是否立即知道這個修改。這個問題在序列程式中是沒有的
在並行中實現可見性需要滿足以下兩個條件:
1.執行緒修改後的共享變數的值能夠及時從工作記憶體重新整理到主記憶體中2.其他執行緒能夠及時把共享變數的最新值從主記憶體更新到自己的工作記憶體中
因此synchronized實現了可見性和原子性:
對於synchronized的操作JMM有兩條規定:
1.執行緒解鎖前,必須把共享變數的最新值重新整理到主記憶體2.執行緒加鎖時,將清空工作記憶體中共享變數的值,從而使用共享變數時需從主記憶體中重新讀取最新的值(加鎖與解鎖需要同一把鎖)
3.有序性
對於序列程式來說,按照順序進行任務是必然的,但是在並行中卻不一樣了
比如1號執行緒要執行兩個變數的賦值,但是第一個變數上了鎖,要等待解鎖,那麼它可能就會先對第二個變數進行賦值(這就是指令重排,是jmm特性,可以提高效能)
這時候2號執行緒去呼叫一號執行緒的第一個變數,但1號執行緒還沒有來得及對它賦值,那麼這時候就沒有保證有序性了。那麼為了保證有序性就要用到volatile關鍵字。
如果你在學習Java的過程中或者在工作中遇到什麼問題都可以來群裡提問,阿里Java高階大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶著大家全面、科學地建立自己的技術體系和技術認知!可以加群找我要課堂連結 注意:是免費的 沒有開發經驗誤入哦! 非喜勿入! 學習交流QQ群:478052716