摘要:總結(jié)中針對(duì)數(shù)組的訪問和賦值的意義應(yīng)該是在于越過對(duì)數(shù)組操作的包裝,進(jìn)而達(dá)到優(yōu)化性能的目的。以上為拋磚引玉。。參考鏈接知乎請(qǐng)問數(shù)組的行為是如何實(shí)現(xiàn)的
在學(xué)習(xí)ConcurrentHashMap時(shí)發(fā)現(xiàn),源碼中對(duì)table數(shù)組的元素進(jìn)行操作時(shí),使用了三個(gè)封裝好的原子操作方法,如下:
/* ---------------- Table element access -------------- */ /* * Atomic access methods are used for table elements as well as * elements of in-progress next table while resizing. All uses of * the tab arguments must be null checked by callers. All callers * also paranoically precheck that tab"s length is not zero (or an * equivalent check), thus ensuring that any index argument taking * the form of a hash value anded with (length - 1) is a valid * index. Note that, to be correct wrt arbitrary concurrency * errors by users, these checks must operate on local variables, * which accounts for some odd-looking inline assignments below. * Note that calls to setTabAt always occur within locked regions, * and so require only release ordering. */ @SuppressWarnings("unchecked") static finalNode tabAt(Node [] tab, int i) { return (Node )U.getObjectAcquire(tab, ((long)i << ASHIFT) + ABASE); } static final boolean casTabAt(Node [] tab, int i, Node c, Node v) { return U.compareAndSetObject(tab, ((long)i << ASHIFT) + ABASE, c, v); } static final void setTabAt(Node [] tab, int i, Node v) { U.putObjectRelease(tab, ((long)i << ASHIFT) + ABASE, v); }
casTabAt這個(gè)方法我們可以很清晰地明白它封裝了對(duì)于數(shù)組元素的cas操作,但是另外兩個(gè)方法的意義如何理解呢?
源碼的作者使用Unsafe直接通過數(shù)組內(nèi)存地址以及索引偏移量去訪問和修改數(shù)組元素的值,和我們直接使用java代碼訪問(arr[i])、賦值(arr[i] = x )有什么區(qū)別呢?
請(qǐng)教了成哥(同事)后得到了一個(gè)重要的點(diǎn):數(shù)組越界異常ArrayIndexOutOfBoundsException
如果java中的數(shù)組和c一樣,僅僅是一個(gè)指針的話,那么也許通過arr[i]訪問和通過內(nèi)存地址訪問不會(huì)有什么區(qū)別,但是由于ArrayIndexOutOfBoundsException這個(gè)眾所周知的異常,我們可以推斷:java中的數(shù)組是經(jīng)過了包裝的
另一個(gè)可以從側(cè)面印證的點(diǎn)是arr.length
大概搜索了一下了解到以下的知識(shí)(不保證正確):
jvm會(huì)為數(shù)組對(duì)象動(dòng)態(tài)創(chuàng)建Class類文件,其標(biāo)識(shí)為[
(HotSpot VM中)java對(duì)象的對(duì)象頭(Object header)內(nèi)會(huì)有一段用于記錄數(shù)組長(zhǎng)度的數(shù)據(jù)
不敢再深挖了,感覺是個(gè)大坑。。
總結(jié):ConcurrentHashMap中針對(duì)table數(shù)組的Unsafe訪問和賦值的意義應(yīng)該是在于越過jvm對(duì)數(shù)組操作的包裝,進(jìn)而達(dá)到優(yōu)化性能的目的。
以上為拋磚引玉。。
參考鏈接:
知乎-請(qǐng)問Java數(shù)組的length行為是如何實(shí)現(xiàn)的?
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/74339.html
摘要:那么,如果之后不是簡(jiǎn)單的操作,而是還有其它業(yè)務(wù)操作,之后才是,比如下面這樣,這該怎么辦呢其它業(yè)務(wù)操作這時(shí)候就沒辦法使用提供的方法了,只能業(yè)務(wù)自己來保證線程安全了,比如下面這樣其它業(yè)務(wù)操作這樣雖然不太友好,但是最起碼能保證業(yè)務(wù)邏輯是正確的。 刪除元素 刪除元素跟添加元素一樣,都是先找到元素所在的桶,然后采用分段鎖的思想鎖住整個(gè)桶,再進(jìn)行操作。 public V remove(Objec...
摘要:原因是它支持多線程進(jìn)行擴(kuò)容操作,而并沒有加鎖。多線程的情況下如果一個(gè)或多個(gè)線程正在對(duì)進(jìn)行擴(kuò)容操作,當(dāng)前線程也要進(jìn)入擴(kuò)容的操作中。 KillCode系列 -- Java篇 原文發(fā)布在我的個(gè)人博客中killCode 因?yàn)镴DK1.8 與 1.7 里對(duì)ConcurrentHashMap 有很多不同的更改以提高性能。所以特別找出類似的方面,進(jìn)行分析。 1. 內(nèi)部參數(shù) //初始容積為 16 p...
摘要:一擴(kuò)容的基本思路中,最復(fù)雜的部分就是擴(kuò)容數(shù)據(jù)遷移,涉及多線程的合作和。單線程注意這兩種情況都是調(diào)用了方法,通過第二個(gè)入?yún)⑦M(jìn)行區(qū)分表示擴(kuò)容后的新數(shù)組,如果為,表示首次發(fā)起擴(kuò)容。第二種情況下,是通過和移位運(yùn)算來保證僅有一個(gè)線程能發(fā)起擴(kuò)容。 showImg(https://segmentfault.com/img/bVbf0J0?w=1000&h=663); 本文首發(fā)于一世流云專欄:http...
摘要:上一篇文章已經(jīng)就進(jìn)行了部分說明,介紹了其中涉及的常量和變量的含義,有些部分需要結(jié)合方法源碼來理解,今天這篇文章就繼續(xù)講解并發(fā)前言本文主要介紹中的一些重要方法,結(jié)合上篇文章中的講解部分進(jìn)行更進(jìn)一步的介紹回顧下上篇文章,我們應(yīng)該已經(jīng)知道的整體結(jié) 上一篇文章已經(jīng)就ConcurrentHashMap進(jìn)行了部分說明,介紹了其中涉及的常量和變量的含義,有些部分需要結(jié)合方法源碼來理解,今天這篇文章就...
摘要:最近準(zhǔn)備面試,一談到基礎(chǔ),大部分面試官上來就數(shù)據(jù)結(jié)構(gòu)素質(zhì)三連與區(qū)別,底層數(shù)據(jù)結(jié)構(gòu),為什么能保證線程安全。數(shù)組順序存儲(chǔ),內(nèi)存連續(xù),查詢快,插入刪除效率稍微低,不過現(xiàn)在略有改善。而在開始,是由和的方式去實(shí)現(xiàn)高并發(fā)下的線程安全。 最近準(zhǔn)備面試,一談到j(luò)ava基礎(chǔ),大部分面試官上來就java數(shù)據(jù)結(jié)構(gòu)素質(zhì)三連:ArrayList與LinkedList區(qū)別,HashMap底層數(shù)據(jù)結(jié)構(gòu),Concur...
閱讀 1181·2021-10-27 14:15
閱讀 2875·2021-10-25 09:45
閱讀 2107·2021-09-02 09:45
閱讀 3437·2019-08-30 15:55
閱讀 1900·2019-08-29 16:05
閱讀 3321·2019-08-28 18:13
閱讀 3172·2019-08-26 13:58
閱讀 525·2019-08-26 12:01