谈一谈Java编程开发中的并发控制
并發(fā)指在宏觀上的同一時(shí)間內(nèi)同時(shí)執(zhí)行多個(gè)任務(wù)。為了滿足這一需求,現(xiàn)代的操作系統(tǒng)都抽象出?線程?的概念,供上層應(yīng)用使用。
這篇博文不打算詳細(xì)展開分析,而是對java并發(fā)中的概念和工具做一個(gè)梳理。
沿著并發(fā)模型、并發(fā)要解決的問題、基本工具、衍生工具這一思路展開。
<!-- more -->
線程
首先線程是什么?線程是由OS抽象并實(shí)現(xiàn)的,我們知道OS的職責(zé)是管理并合理分配硬件資源,那么OS為了更好的管理、分配CPU資源,同時(shí)也為了滿足同時(shí)執(zhí)行任務(wù)這一需求,設(shè)計(jì)了線程這一概念。
雖然java程序運(yùn)行在JVM虛擬機(jī)上,但是java的線程仍然是對操作系統(tǒng)原生線程的封裝,同時(shí),jvm對線程實(shí)現(xiàn)時(shí)也將jvm的運(yùn)行棧設(shè)計(jì)成線程私有內(nèi)存,因此,java線程和原生線程在理解上實(shí)際上沒太大區(qū)別。
線程的五種狀態(tài):
graph LR 新建 --> 就緒; 就緒 --> 運(yùn)行; 運(yùn)行 --> 就緒; 運(yùn)行 --> 阻塞; 阻塞 --> 就緒; 運(yùn)行 --> 死亡;先來看上面的就緒狀態(tài)和運(yùn)行狀態(tài)。我們知道線程雖然宏觀上是同時(shí)執(zhí)行的,但是微觀上使用如時(shí)間片輪轉(zhuǎn)算法使得線程依次執(zhí)行。那么,同一時(shí)間只有一個(gè)線程執(zhí)行,其它需要執(zhí)行的線程處于?就緒隊(duì)列?中,等待自己被調(diào)度到。
而如果線程想要暫時(shí)放棄在CPU上運(yùn)行的權(quán)利,就會阻塞自己。這時(shí)對應(yīng)著阻塞狀態(tài),同時(shí)線程會從就緒隊(duì)列中移除,進(jìn)入等待隊(duì)列。
很顯然,阻塞線程被喚醒肯定是進(jìn)入就緒隊(duì)列等待調(diào)度,而不可能是直接分配到CPU上運(yùn)行。
在線程同步時(shí),線程可能由于以下情況被阻塞:
并發(fā)需要解決的問題
功能性問題
線程同步面臨兩個(gè)問題,想象下有兩個(gè)線程在協(xié)作工作完成某項(xiàng)任務(wù)。那么需要解決以下問題:
性能和可用性問題
在多線程程序的性能問題上,如果是對于同樣一段臨界區(qū)的多線程訪問,那么則有以下幾個(gè)思路:
以上三種思路的性能優(yōu)劣沒有一個(gè)普適的結(jié)果,和具體的場景相關(guān)。
并發(fā)中還會出現(xiàn)以下幾種情況導(dǎo)致系統(tǒng)不可用:
并發(fā)代碼的幾個(gè)性質(zhì)
并發(fā)編程中需要考慮的幾個(gè)概念:
從我個(gè)人的理解來看,原子性屬于由并發(fā)和線程這一理論概念自然而然推導(dǎo)衍生而來的概念,而可見性和有序性是具體的工程實(shí)踐中產(chǎn)生的。
實(shí)際中,jvm并不能實(shí)現(xiàn)的特別完美,總會有工程上的妥協(xié)。理論模型與實(shí)際模型無法完美契合,總存在一定的偏差。
比如說,jvm為了向性能妥協(xié)使用了緩存機(jī)制,犧牲了數(shù)據(jù)一致性,這就產(chǎn)生了可見性的概念,需要程序員編程時(shí)自己控制。
jvm為了指令更高效率的執(zhí)行進(jìn)行了指令重排優(yōu)化,則產(chǎn)生了有序性的問題。印象里以前大學(xué)里學(xué)過的CPU的流水線技術(shù),為了指令能夠更好的被CPU流水線利用,減少流水線的空閑時(shí)間,編譯器編譯時(shí)也會在不影響?串行語義?的前提下,進(jìn)行指令重排。
總而言之,這是在性能和理論模型完整性之間的一種妥協(xié)。
并發(fā)的工具
技術(shù)上的工具、概念繁多復(fù)雜,但是如果我們能理解技術(shù)設(shè)計(jì)上無時(shí)無刻的不運(yùn)用抽象和分層的手段,
那么,我們可以把技術(shù)上的工具分為兩種:
更高層次的工具對基礎(chǔ)工具進(jìn)行了抽象和封裝,屏蔽了其中的實(shí)現(xiàn)細(xì)節(jié)。
這里想強(qiáng)調(diào)的是,工具的接口和實(shí)現(xiàn)是分開的,兩者可以沒有關(guān)系。
如java的監(jiān)視器鎖從接口上來看,其語義和互斥鎖一樣。然而它并不一定使用互斥鎖實(shí)現(xiàn),而是可以為了性能存在優(yōu)化,只要最終的行為與接口相同即可。
基本工具
鎖、條件變量、信號量
有三種用于線程同步的工具:
- 互斥鎖。使用信號量實(shí)現(xiàn)。臨界區(qū)外等待的線程會被阻塞。
- 自旋鎖。臨界區(qū)外等待的線程會忙等。
?
在java中,Object類有wait()、notify()和notifyAll()之類的方法。
這些方法可以認(rèn)為每個(gè)對象都內(nèi)置了一個(gè)條件變量,而這些方法是對這些條件變量的操作,因此,可以使用這些方法將對象當(dāng)作條件變量使用,從而做到線程的同步。
為了讓學(xué)習(xí)變得輕松、高效,今天給大家免費(fèi)分享一套Java入門教學(xué)資源。幫助大家在成為Java架構(gòu)師的道路上披荊斬棘。需要資料的歡迎加入學(xué)習(xí)交流群:9285,05736
總結(jié)
以上是生活随笔為你收集整理的谈一谈Java编程开发中的并发控制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python实现xmind_Python
- 下一篇: 让初学者不迷茫的Java学习方法有很多?