摘要:因?yàn)槎嗑€程競(jìng)爭(zhēng)鎖時(shí)會(huì)引起上下文切換。減少線程的使用。舉個(gè)例子如果說服務(wù)器的帶寬只有,某個(gè)資源的下載速度是,系統(tǒng)啟動(dòng)個(gè)線程下載該資源并不會(huì)導(dǎo)致下載速度編程,所以在并發(fā)編程時(shí),需要考慮這些資源的限制。
最近私下做一項(xiàng)目,一bug幾日未解決,總惶恐。一日頓悟,bug不可怕,怕的是項(xiàng)目不存在bug,與其懼怕,何不與其剛正面。
系列文章傳送門:
Java多線程學(xué)習(xí)(一)Java多線程入門
Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1)
Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(2)
Java多線程學(xué)習(xí)(三)volatile關(guān)鍵字
Java多線程學(xué)習(xí)(四)等待/通知(wait/notify)機(jī)制
Java多線程學(xué)習(xí)(五)線程間通信知識(shí)點(diǎn)補(bǔ)充
Java多線程學(xué)習(xí)(六)Lock鎖的使用
本節(jié)思維導(dǎo)圖:
關(guān)注微信公眾號(hào):“Java面試通關(guān)手冊(cè)” 回復(fù)“Java多線程”獲取思維導(dǎo)圖源文件和思維導(dǎo)圖軟件。
并發(fā)編程的目的就是為了能提高程序的執(zhí)行效率提高程序運(yùn)行速度,但是并發(fā)編程并不總是能提高程序運(yùn)行速度的,而且并發(fā)編程可能會(huì)遇到很多問題,比如:內(nèi)存泄漏、上下文切換、死鎖還有受限于硬件和軟件的資源閑置問題。
多線程就是幾乎同時(shí)執(zhí)行多個(gè)線程(一個(gè)處理器在某一個(gè)時(shí)間點(diǎn)上永遠(yuǎn)都只能是一個(gè)線程!即使這個(gè)處理器是多核的,除非有多個(gè)處理器才能實(shí)現(xiàn)多個(gè)線程同時(shí)運(yùn)行)。CPU通過給每個(gè)線程分配CPU時(shí)間片來實(shí)現(xiàn)偽同時(shí)運(yùn)行,因?yàn)镃PU時(shí)間片一般很短很短,所以給人一種同時(shí)運(yùn)行的感覺。
上下文切換當(dāng)前任務(wù)在執(zhí)行完CPU時(shí)間片切換到另一個(gè)任務(wù)之前會(huì)先保存自己的狀態(tài),以便下次再切換會(huì)這個(gè)任務(wù)時(shí),可以再加載這個(gè)任務(wù)的狀態(tài)。任務(wù)從保存到再加載的過程就是一次上下文切換。
上下文切換通常是計(jì)算密集型的。也就是說,它需要相當(dāng)可觀的處理器時(shí)間,在每秒幾十上百次的切換中,每次切換都需要納秒量級(jí)的時(shí)間。所以,上下文切換對(duì)系統(tǒng)來說意味著消耗大量的 CPU 時(shí)間,事實(shí)上,可能是操作系統(tǒng)中時(shí)間消耗最大的操作。
Linux相比與其他操作系統(tǒng)(包括其他類 Unix 系統(tǒng))有很多的優(yōu)點(diǎn),其中有一項(xiàng)就是,其上下文切換和模式切換的時(shí)間消耗非常少。
那么我們現(xiàn)在可能會(huì)考慮 :如何減少上下文切換的次數(shù)呢???
減少上下文切換
這是《Java并發(fā)編程的藝術(shù)》的作者方騰飛大佬嗎????
上下文切換又分為2種:讓步式上下文切換和搶占式上下文切換。前者是指執(zhí)行線程主動(dòng)釋放CPU,與鎖競(jìng)爭(zhēng)嚴(yán)重程度成正比,可通過減少鎖競(jìng)爭(zhēng)和使用CAS算法來避免;后者是指線程因分配的時(shí)間片用盡而被迫放棄CPU或者被其他優(yōu)先級(jí)更高的線程所搶占,一般由于線程數(shù)大于CPU可用核心數(shù)引起,可通過適當(dāng)減少線程數(shù)和使用協(xié)程來避免。
總結(jié)一下:
減少鎖的使用。因?yàn)槎嗑€程競(jìng)爭(zhēng)鎖時(shí)會(huì)引起上下文切換。
使用CAS算法。這種算法也是為了減少鎖的使用。CAS算法是一種無鎖算法。
減少線程的使用。人物很少的時(shí)候創(chuàng)建大量線程會(huì)導(dǎo)致大量線程都處于等待狀態(tài)。
使用協(xié)程。
我們上面提到了兩個(gè)名詞:“CAS算法” 和 “協(xié)程”。可能有些人不是很了解這倆東西,所以這里簡單說一下。。。
CAS算法
CAS(比較與交換,Compare and swap) 是一種有名的無鎖算法。無鎖編程,即不使用鎖的情況下實(shí)現(xiàn)多線程之間的變量同步,也就是在沒有線程被阻塞的情況下實(shí)現(xiàn)變量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。實(shí)現(xiàn)非阻塞同步的方案稱為“無鎖編程算法”( Non-blocking algorithm)。
相對(duì)應(yīng)的,獨(dú)占鎖是一種悲觀鎖,synchronized就是一種獨(dú)占鎖,它假設(shè)最壞的情況,并且只有在確保其它線程不會(huì)造成干擾的情況下執(zhí)行,會(huì)導(dǎo)致其它所有需要鎖的線程掛起,等待持有鎖的線程釋放鎖。
協(xié)程
協(xié)程也可以說是微線程或者說是輕量級(jí)的線程,它占用的內(nèi)存更少并且更靈活。很多編程語言中都有協(xié)程。Lua, Ruby 等等都有自己的協(xié)程實(shí)現(xiàn)。Go完全就是因?yàn)閰f(xié)程而發(fā)展壯大的。維基百科上面并沒有Java實(shí)現(xiàn)協(xié)程的方式,但是不代表Java不能實(shí)現(xiàn)協(xié)程。比如可以使用Java實(shí)現(xiàn)的開源協(xié)程庫:Quasar。Quasar官網(wǎng):http://www.paralleluniverse.co/quasar/,。這個(gè)庫實(shí)現(xiàn)了一種可以和Go語言中的Goroutine相對(duì)標(biāo)的編程概念:Fiber。Fiber是一種真正的協(xié)程。
最后Mark兩篇關(guān)于協(xié)程的文章:
協(xié)程,高并發(fā)IO終極殺器(3):https://zhuanlan.zhihu.com/p/27590299
次時(shí)代Java編程(一):Java里的協(xié)程:http://geek.csdn.net/news/detail/71824
避免死鎖在操作系統(tǒng)中,死鎖是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過程中,由于競(jìng)爭(zhēng)資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去。此時(shí)稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱為死鎖進(jìn)程。
在線程中,如果兩個(gè)線程同時(shí)等待對(duì)方釋放鎖也會(huì)產(chǎn)生死鎖。
鎖是一個(gè)好東西,但是使用不當(dāng)就會(huì)造成死鎖。一旦死鎖產(chǎn)生程序就無法繼續(xù)運(yùn)行下去。所以如何避免死鎖的產(chǎn)生,在我們使用并發(fā)編程時(shí)至關(guān)重要。
根據(jù)《Java并發(fā)編程的藝術(shù)》有下面四種避免死鎖的常見方法:
避免一個(gè)線程同時(shí)獲得多個(gè)鎖
避免一個(gè)線程在鎖內(nèi)同時(shí)占用多個(gè)資源,盡量保證每個(gè)鎖只占用一個(gè)資源
嘗試使用定時(shí)鎖,使用lock.tryLock(timeout)來替代使用內(nèi)部鎖機(jī)制
對(duì)于數(shù)據(jù)庫鎖,加鎖和解鎖必須在一個(gè)數(shù)據(jù)庫連接里,否則會(huì)出現(xiàn)解鎖失敗的情況
解決資源限制這里我覺得《Java并發(fā)編程的藝術(shù)》講的還是挺好的。
什么是資源限制???
所謂資源限制就是我們?cè)谶M(jìn)行并發(fā)編程時(shí),程序的運(yùn)行速度受限于計(jì)算機(jī)硬件資源比如CPU,內(nèi)存等等或軟件資源比如軟件的質(zhì)量、性能等等。舉個(gè)例子:如果說服務(wù)器的帶寬只有2MB/s,某個(gè)資源的下載速度是1MB/s,系統(tǒng)啟動(dòng)10個(gè)線程下載該資源并不會(huì)導(dǎo)致下載速度編程10MB/s,所以在并發(fā)編程時(shí),需要考慮這些資源的限制。硬件資源限制有:帶寬的上傳和下載速度、硬盤讀寫速度和CPU處理速度;軟件資源限制有數(shù)據(jù)庫的連接數(shù)、socket連接數(shù)、軟件質(zhì)量和性能等等。
資源限制引發(fā)的問題
在并發(fā)編程中,程序運(yùn)行加快的原因是運(yùn)行方式從串行運(yùn)行變?yōu)椴l(fā)運(yùn)行,但是如果如果某段程序的并發(fā)執(zhí)行由于資源限制仍然在串行執(zhí)行的話,這時(shí)候程序的運(yùn)行不僅不會(huì)加快,反而會(huì)更慢,因?yàn)榭赡茉黾恿松舷挛那袚Q和資源調(diào)度的時(shí)間。
如何解決資源限制的問題
對(duì)于硬件資源限制,可以考慮使用集群并行執(zhí)行程序。既然單機(jī)的資源有限制,那么就讓程序在多機(jī)上運(yùn)行。比如使用Hadoop或者自己搭建服務(wù)器集群。對(duì)于軟件資源的限制,可以考慮使用資源池將資源復(fù)用。比如使用連接池將數(shù)據(jù)庫和Socket復(fù)用,或者在調(diào)用對(duì)方webservice接口獲取數(shù)據(jù)時(shí),只建立一個(gè)連接。另外還可以考慮使用良好的開源軟件。
在資源限制的情況下如何進(jìn)行并發(fā)編程
根據(jù)不同的資源限制調(diào)整程序的并發(fā)度,比如下載文件程序依賴于兩個(gè)資源-帶寬和硬盤讀寫速度。有數(shù)據(jù)庫操作時(shí),設(shè)計(jì)數(shù)據(jù)庫練連接數(shù),如果SQL語句執(zhí)行非???,而線程的數(shù)量比數(shù)據(jù)庫連接數(shù)大很多,則某些線程會(huì)被阻塞,等待數(shù)據(jù)庫連接。
參考:
維基百科,百度百科
《Java并發(fā)編程的藝術(shù)》
上下文切換的詳解:http://ifeve.com/context-swit...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69002.html
摘要:相比與其他操作系統(tǒng)包括其他類系統(tǒng)有很多的優(yōu)點(diǎn),其中有一項(xiàng)就是,其上下文切換和模式切換的時(shí)間消耗非常少。因?yàn)槎嗑€程競(jìng)爭(zhēng)鎖時(shí)會(huì)引起上下文切換。減少線程的使用。很多編程語言中都有協(xié)程。所以如何避免死鎖的產(chǎn)生,在我們使用并發(fā)編程時(shí)至關(guān)重要。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)syn...
摘要:三關(guān)鍵字能保證原子性嗎并發(fā)編程藝術(shù)這本書上說保證但是在自增操作非原子操作上不保證,多線程編程核心藝術(shù)這本書說不保證。多線程訪問關(guān)鍵字不會(huì)發(fā)生阻塞,而關(guān)鍵字可能會(huì)發(fā)生阻塞關(guān)鍵字能保證數(shù)據(jù)的可見性,但不能保證數(shù)據(jù)的原子性。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)synchroniz...
摘要:轉(zhuǎn)載請(qǐng)備注地址多線程學(xué)習(xí)二將分為兩篇文章介紹同步方法另一篇介紹同步語句塊。如果兩個(gè)線程同時(shí)操作對(duì)象中的實(shí)例變量,則會(huì)出現(xiàn)非線程安全,解決辦法就是在方法前加上關(guān)鍵字即可。 轉(zhuǎn)載請(qǐng)備注地址: https://blog.csdn.net/qq_3433... Java多線程學(xué)習(xí)(二)將分為兩篇文章介紹synchronized同步方法另一篇介紹synchronized同步語句塊。系列文章傳送門...
摘要:第一個(gè)字被稱為。經(jīng)量級(jí)鎖的加鎖過程當(dāng)一個(gè)對(duì)象被鎖定時(shí),被復(fù)制到當(dāng)前嘗試獲取鎖的線程的線程棧的鎖記錄空間被復(fù)制的官方稱為。根據(jù)鎖對(duì)象目前是否處于被鎖定狀態(tài),撤銷偏向后恢復(fù)到未鎖定或經(jīng)量級(jí)鎖定狀態(tài)。 Synchronized關(guān)鍵字 synchronized的鎖機(jī)制的主要優(yōu)勢(shì)是Java語言內(nèi)置的鎖機(jī)制,因此,JVM可以自由的優(yōu)化而不影響已存在的代碼。 任何對(duì)象都擁有對(duì)象頭這一數(shù)據(jù)結(jié)構(gòu)來支持鎖...
摘要:如何在線程池中提交線程內(nèi)存模型相關(guān)問題什么是的內(nèi)存模型,中各個(gè)線程是怎么彼此看到對(duì)方的變量的請(qǐng)談?wù)動(dòng)惺裁刺攸c(diǎn),為什么它能保證變量對(duì)所有線程的可見性既然能夠保證線程間的變量可見性,是不是就意味著基于變量的運(yùn)算就是并發(fā)安全的請(qǐng)對(duì)比下對(duì)比的異同。 并發(fā)編程高級(jí)面試面試題 showImg(https://upload-images.jianshu.io/upload_images/133416...
閱讀 711·2021-11-18 10:07
閱讀 2909·2021-09-22 16:04
閱讀 908·2021-08-16 10:50
閱讀 3403·2019-08-30 15:56
閱讀 1810·2019-08-29 13:22
閱讀 2868·2019-08-26 17:15
閱讀 1304·2019-08-26 10:57
閱讀 1136·2019-08-23 15:23