ArrayList併發問題分析

2021-08-20 20:45:45 字數 2644 閱讀 5858

1.問題描述:

for迴圈執行緒池中啟10個任務進行list.add(),加完後,發現第乙個值為空,而且list的size也不是10

2.分析:

執行緒問題比較不好分析,主要是太抽象,都隱藏在後台,不能直觀的觀察到,而且時有時無,所以比較難分析

1.第一步,出這種問題,首先確定,肯定是共享變數,非原子化操作引起的

arraylist的add方法很簡單,就下面這兩句

ensurecapacityinternal(size+ 1);  // increments modcount!!

elementdata[size++] = e;

第一句是擴容,可以排除(其實也有關係),直覺上應該是size++這個操作不是原子性的引起的

2.第二步,給自己插上想象的雞翅膀

2.1 size小的原因,我猜如下:

最後的幾個add,size++都在前乙個執行緒沒有加完的基礎上++,導致最後的幾個物件都加到最後乙個位置上

(有待推敲,因為有擴容因素)

2.2 第乙個為空的原因,我猜如下:

最開始的為空,第乙個執行緒準備size++,第二個執行緒已經size++好了,導致兩個執行緒都加到了第二個位置上,

第乙個沒人設定,所以為空(也不太確定,都走到size++,放置的時候size已經+2了,但為什麼中間沒有null的出現?)

好,分析完畢

可能是上面的原因,但是很多細節經不起推敲

比如這一步,如果是空的話,就會將size設定為預設值10,但是實際有size為9,或者8的情況

ensurecapacityinternal(size+ 1);  // increments modcount!!

說明了什麼?這一步沒有執行,直接到1,然後用它的演算法size=size+size>>1進行擴容,

其實不是沒有執行是他自己有自定義的序列化方式,自己的size跟這個elementdata的length無關

為什麼沒執行?就算再怎麼亂序,也至少會有乙個執行緒是從size=0開始執行的,只要是0就會預設將arraylist copy進乙個size為10的新list裡

private voidensurecapacityinternal(intmincapacity) 

ensureexplicitcapacity(mincapacity);

}

ensureexplicitcapacity這裡執行的是下面的**:如果新長度大於arr的長度,就grow他
if(mincapacity -elementdata.length> 0)

grow(mincapacity);

grow**如下:拿到老size,將新size和老size的3/2進行比較,取大的將arr copy進去
intoldcapacity =elementdata.length;

intnewcapacity = oldcapacity + (oldcapacity >> 1);

if(newcapacity - mincapacity < 0)

newcapacity = mincapacity;

if(newcapacity -max_array_size> 0)

newcapacity = hugecapacity(mincapacity);

// mincapacity is usually close to size, so this is a win:

elementdata= arrays.copyof(elementdata, newcapacity);

後來發現arraylist有自己的序列化邏輯,所以裡面的arr通過fastjson的序列化方式列印出來可能不對,

size可能是錯的,它裡面的elementdata是自定義的序列化,其實這段話沒有意義,跟序列化無關

第乙個值為空可能是因為兩線程copy和賦值錯序了,第乙個執行緒size++=e了,第二個執行緒copy將空的賦進去,把第乙個置空了,但為什麼只有第乙個為空?因為之後的至少都有值,不會有把空copy進arraylist裡的情況

綜上所述,加粗的兩段話分別是arraylist在併發情況下size小和第乙個為空的原因,也是我瞎猜的,但估計也差不多

總結如下:

1.執行緒併發問題,首要就分析共享變數

2.object物件的序列化方法很重要

3.寫的太粗糙了,以後再改

解決併發問題

一.使用redis鎖 智慧型雲 工單系統 搶單 工單id鎖key public static final string cloud live gain order lock orderid cloud live gain order lock orderid component public cla...

Connection併發問題

connection lock getconnection lock.setautocommit false lock.createstatement execute select from zhaojianyong for update final connection connection ge...

hive併發問題

hive 併發模型 使用案例 併發支援 是資料庫的必須,而且他們的使用案例很好懂。至少,我們要盡可能支援併發讀和寫。新增幾個發現當前已經鎖定的鎖,是有用的。這裡沒有乙個直接的需求新增乙個api顯式獲取鎖,所以,所有鎖都是隱式獲取的。hive定義一下模式的鎖 注意不需要意向鎖 共享 s 排他 x 見名...