Java中的ConcurrentLinkedQueue松散隊(duì)列解析
一、為什么叫松散隊(duì)列?
唯一一個(gè)使用cas實(shí)現(xiàn)的線程安全并發(fā)效率高的集合。
鏈表是松散的,鏈表節(jié)點(diǎn)并不都是有效的,允許存在無(wú)效節(jié)點(diǎn)val=null,但是只有最后一個(gè)節(jié)點(diǎn)才能next=null 為什么線程安全需要把鏈表做成松散的。就是因?yàn)槿腙?duì)分為兩步,cas設(shè)置最后一個(gè)節(jié)點(diǎn)的next,和cas設(shè)置tail,兩個(gè)操作之間并無(wú)原子性,所以可能并發(fā)操作了多個(gè)cas設(shè)置next,才設(shè)置tail。tail滯后很多。 出隊(duì)的時(shí)候,也需要分為兩步,cas將值設(shè)置成null。cas移動(dòng)head。head也會(huì)滯后很多。所以會(huì)有很多節(jié)點(diǎn)已經(jīng)出隊(duì)為null,但是依然可以遍歷到。因此叫做松散隊(duì)列。
二、如何實(shí)現(xiàn)線程安全?
add入隊(duì)操作
tail節(jié)點(diǎn)并不是最后一個(gè)節(jié)點(diǎn)
1、從 tail 節(jié)點(diǎn)開(kāi)始遍歷到尾節(jié)點(diǎn),若定位到尾節(jié)點(diǎn)(p.next == null),則入隊(duì)。
2、遍歷過(guò)程中,如果遍歷到無(wú)效節(jié)點(diǎn)(p.next == p)說(shuō)明p已經(jīng)并發(fā)出隊(duì),需要重新從有效節(jié)點(diǎn)(tail 或 head)開(kāi)始遍歷。
3、遍歷過(guò)程中,時(shí)刻關(guān)注 tail 節(jié)點(diǎn)是否無(wú)效。若無(wú)效了需要重新從最新的 tail(如果tail失效,從head) 開(kāi)始遍歷,否則繼續(xù)遍歷當(dāng)前的下一個(gè)節(jié)點(diǎn)。
4、找到最后一個(gè)節(jié)點(diǎn)后,進(jìn)行入隊(duì)操作,使用cas將next修改為新節(jié)點(diǎn),如果tail->next!=null,需要使用cas將tail設(shè)置為新節(jié)點(diǎn)。
cas設(shè)置next,和cas設(shè)置tail,兩個(gè)操作之間并無(wú)原子性,所以可能并發(fā)操作了多個(gè)cas設(shè)置next,才設(shè)置tail。tail滯后很多。
如下圖B節(jié)點(diǎn)已經(jīng)被poll了,tail還在B節(jié)點(diǎn)前面。tail失效了,從tail無(wú)法遍歷到最后一個(gè)節(jié)點(diǎn)。
poll出隊(duì)操作
1、從 head 節(jié)點(diǎn)開(kāi)始遍歷找出首個(gè)有效節(jié)點(diǎn)(p.item != null),返回該節(jié)點(diǎn)的數(shù)據(jù)(p.item)。
2、遍歷過(guò)程中,如果遍歷到尾節(jié)點(diǎn)(p.next == null),則返回空。
3、遍歷過(guò)程中,如果遍歷到無(wú)效節(jié)點(diǎn)(p.next == p),說(shuō)明其他線程修改了 head,需要重新從有效節(jié)點(diǎn)(新的 head)開(kāi)始遍歷。
4、cas將值設(shè)置成null。cas移動(dòng)head。
5、更新head,需要注意的是,并不是每次出隊(duì)時(shí)都執(zhí)行 updateHead() 更新 head 節(jié)點(diǎn): 當(dāng) head 節(jié)點(diǎn)里有元素時(shí),直接彈出 head 節(jié)點(diǎn)里的元素,設(shè)置為null,而不會(huì)更新 head 節(jié)點(diǎn)。
只有當(dāng) head 節(jié)點(diǎn)里沒(méi)有元素時(shí),出隊(duì)操作才會(huì)更新 head 節(jié)點(diǎn)。
三、優(yōu)缺點(diǎn)
從它的入隊(duì)出隊(duì)機(jī)制就可以看出,優(yōu)缺點(diǎn)非常明顯。
優(yōu)點(diǎn): 1、并發(fā)效率高,入隊(duì)出隊(duì)不需要加鎖進(jìn)行線程同步,全程使用cas操作
缺點(diǎn): 1、入隊(duì)出隊(duì)都分為兩步cas,cas之間是控制不了的,所以會(huì)產(chǎn)生tail滯后,tail失效,鏈表節(jié)點(diǎn)poll了,還可以繼續(xù)訪問(wèn)沒(méi)有釋放,內(nèi)存是松散的,無(wú)效節(jié)點(diǎn)占用內(nèi)存,內(nèi)存開(kāi)銷大。
2、由于head和tail都不是嚴(yán)格指向頭尾,每次poll,add都需要遍歷,浪費(fèi)時(shí)間效率。concurrentLinkedQueue存的元素越多,效率越低。因此只適合高并發(fā)小容量的場(chǎng)景使用。
3、size獲取大小也要遍歷所有節(jié)點(diǎn)才行
到此這篇關(guān)于Java中的ConcurrentLinkedQueue松散隊(duì)列解析的文章就介紹到這了,更多相關(guān)ConcurrentLinkedQueue松散隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring MVC創(chuàng)建項(xiàng)目踩過(guò)的bug
這篇文章主要介紹了Spring MVC創(chuàng)建項(xiàng)目踩過(guò)的bug,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11SpringAOP如何修改請(qǐng)求參數(shù)列表
這篇文章主要介紹了SpringAOP如何修改請(qǐng)求參數(shù)列表問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03RabbitMQ 的消息持久化與 Spring AMQP 的實(shí)現(xiàn)詳解
這篇文章主要介紹了RabbitMQ 的消息持久化與 Spring AMQP 的實(shí)現(xiàn)剖析詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08jsp+dao+bean+servlet(MVC模式)實(shí)現(xiàn)簡(jiǎn)單用戶登錄和注冊(cè)頁(yè)面
這篇文章主要介紹了jsp+dao+bean+servlet(MVC模式)實(shí)現(xiàn)簡(jiǎn)單用戶登錄和注冊(cè)頁(yè)面,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12反射機(jī)制:getDeclaredField和getField的區(qū)別說(shuō)明
這篇文章主要介紹了反射機(jī)制:getDeclaredField和getField的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Java 5個(gè)人坐在一起(有關(guān)第五個(gè)人歲數(shù)的問(wèn)題)
利用遞歸的方法,遞歸分為回推和遞推兩個(gè)階段。要想知道第五個(gè)人歲數(shù),需知道第四人的歲數(shù),依次類推,推到第一人(10歲),再往回推,需要的朋友可以參考下2017-02-02ArrayList的自動(dòng)擴(kuò)充機(jī)制實(shí)例解析
本文主要介紹了ArrayList的自動(dòng)擴(kuò)充機(jī)制,由一個(gè)題目切入主題,逐步向大家展示了ArrayList的相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10IDEA使用JDBC安裝配置jar包連接MySQL數(shù)據(jù)庫(kù)
這篇文章介紹了IDEA使用JDBC安裝配置jar包連接MySQL數(shù)據(jù)庫(kù)的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01Java編程中的性能優(yōu)化如何實(shí)現(xiàn)
這篇文章主要介紹了Java編程中的性能優(yōu)化如何實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10