目錄copyonwritearraylist通過讀寫分離的形式重構arraylist,保證arraylist在迴圈遍歷過程中的讀寫分離性,保證陣列的最終一致性,適用於多讀少寫的情景下。
。
//可重入鎖,實現併發控制
final transient reentrantlock lock = new reentrantlock();
/** the array, accessed only via getarray/setarray. */
//儲存原始陣列物件
private transient volatile object array;
lock 實現寫時加鎖的控制
object array儲存需要的資料
主要解析包括以下幾個方法
兩個方式的拷貝:第一種方式是如果是相同的直接進行引用即可,第二種方式通過重新賦值陣列並且進行陣列元素型別的轉化來實現。public copyonwritearraylist(collection extends e> c)
setarray(elements);
}
private static boolean eq(object o1, object o2)
用於判斷兩個物件是否相等,元素可能存在null,需要重寫方法不能使用類似與o1.equals(o2)
的方式會導致npe。
主要流程:/** 替換指定index上的元素*/
public e set(int index, e element) else
return oldvalue;
} finally
}
上鎖獲取index上的物件
檢視兩個是否相等
不相等則copy新的陣列
修改新的陣列並修改引用
解鎖set方法為寫方法,需要繼續進行加鎖,實現多個寫之間的一致性。
記錄index上的元素oldvalue,如果兩個位址是不完全一致的就複製原有陣列並進行元素的修改,最後複製回去。
為什麼使用==
進行比較而不是eq(a,b)
array中實際儲存的是物件陣列,array不同於hash需要使用hashcode和equals函式來進行判斷
主要流程:public boolean add(e e) finally
}
上鎖拷貝長度為len+1的新陣列
進行複製
修改引用
解鎖從add中就能看出陣列的長度變化情況,與arraylist不同的擴容機制,cow的陣列並不含有空餘空間,陣列完全飽和
向指定位置上新增元素的方法
主要流程:public void add(int index, e element)
newelements[index] = element;
setarray(newelements);
} finally
}
上鎖確定右側需要移動的元素
需要移動的元素為0
直接進行擴容
需要移動的元素不為0
進行陣列擴容
分左右兩側進行複製
替換位置上的值
解鎖
主要流程:public boolean addifabsent(e e)
/** * a version of addifabsent using the strong hint that given
* recent snapshot does not contain e.
*/private boolean addifabsent(e e, object snapshot)
object newelements = arrays.copyof(current, len + 1);
newelements[len] = e;
setarray(newelements);
return true;
} finally
}
其中有很多非常有意思的小細節
第乙個:先進行了無鎖化的查詢,看是否存在元素,當不存在時再新增。而不是直接進行上鎖在判斷元素是否存在
第二個:正是由於上面的無鎖化操作,導致快照和當前陣列可能不一致,但依然利用上了快照資訊,其中有個比較有意思的問題是沒有直接使用indexof進行重新查詢,而是附加了比較查詢,這裡有個很底層的問題就是==
和!=
的比較速度要比indexof中的eq()的速度快得多,加之對於array大部分的操作都是add
或者add(index,e)
,如果index
的值較大的話對於效率的提公升會更加高。
這裡addifabsent(index,e)需要兩步:確認是否存在和新增,將第一步的查詢不加鎖,而第二步修改進行加鎖,實屬精髓
azkaban web server原始碼解析
azkaban主要用於hadoop相關job任務的排程,但也可以應用任何需要排程管理的任務,可以完全代替crontab。azkaban主要分為web server 任務上傳,管理,排程 executor server 接受web server的排程指令,進行任務執行 1.資料表 projects 工...
JDK LinkedHashMap原始碼解析
今天來分析一下jdk linkedhashmap的源 public class linkedhashmapextends hashmapimplements map可以看到,linkedhashmap繼承自hashmap,並且也實現了map介面,所以linkedhashmap沿用了hashmap的大...
Redux原始碼createStore解讀常用方法
const store createstore reducer,preloadedstate enhancer 直接返回當前currentstate,獲取state值,return state 我覺得應該深轉殖乙個新的物件返回,不然有可能會被外部修改 function getstate consol...