Disruptor剖析

Disruptor是什麼?

    Disruptor 是線程內通訊框架,用於線程裏共享數據。LMAX 建立Disruptor做爲可靠消息架構的一部分並將它設計成一種在不一樣組件中共享數據很是快的方法。編程

(一)Disruptor中的併發

    採用RingBuffer無鎖隊列的實現,對於傳統併發隊列,至少要維護兩個指針,一個頭指針和一個尾指針。在併發訪問修改時,頭指針和尾指針的維護不可避免的應用了鎖。Disruptor因爲是環狀隊列,對於Producer而言只有頭指針,並且鎖是樂觀鎖,在標準Disruptor應用中,只有一個生產者,避免了頭指針鎖的爭用。因此,咱們能夠理解Disruptor爲無鎖隊列。緩存

    lock-free, 不使用鎖, 使用CAS(Compare And Swap/Set) 嚴格意義上說仍然是使用鎖, 由於CAS本質上也是一種樂觀鎖, 只不過是CPU級別指令, 不涉及到操做系統, 因此效率很高 。多線程

CAS優勢

CAS依賴於處理器的支持, 固然大部分現代處理器都支持;
CAS相對於鎖是很是高效的, 由於它不須要涉及內核上下文切換進行仲裁;
但CAS並非免費的, 它會涉及到對指令pipeline加鎖, 而且會用到內存barrier(用來刷新內存狀態,簡單理解就是把緩存中,寄存器中的數據同步到內存中去);架構

參考:http://ifeve.com/locks-are-bad/併發

(二)緩存行填充

    緩存是由緩存行組成的,一般是64字節,而且它有效地引用主內存中的一塊地址。一個Java的long類型是8字節,所以在一個緩存行中能夠存8個long類型的變量。框架

    解決問題:避免RingBuffer head和tail指針在統一個緩存行,多線程獲取時,head和tail的獲取相互不影響,避免寫衝突。高併發

爲何追加64字節可以提升併發編程的效率呢性能

    由於對於英特爾酷睿i7,酷睿, Atom和NetBurst, Core Solo和Pentium M處理器的L1,L2或L3緩存的高速緩存行是64個字節寬,不支持部分填充緩存行,這意味着若是隊列的頭節點和尾節點都不足64字節的話,處理器會將它們都讀到同一個高速緩存行中,在多處理器下每一個處理器都會緩存一樣的頭尾節點,當一個處理器試圖修改頭接點時會將整個緩存行鎖定,那麼在緩存一致性機制的做用下,會致使其餘處理器不能訪問本身高速緩存中的尾節點,而隊列的入隊和出隊操做是須要不停修改頭接點和尾節點,因此在多處理器的狀況下將會嚴重影響到隊列的入隊和出隊效率。Doug lea使用追加到64字節的方式來填滿高速緩衝區的緩存行,避免頭接點和尾節點加載到同一個緩存行,使得頭尾節點在修改時不會互相鎖定。spa

是否是在使用變量時都應該追加到64字節呢?操作系統

    不是的。在兩種場景下不該該使用這種方式。第一:緩存行非64字節寬的處理器,如P6系列和奔騰處理器,它們的L1和L2高速緩存行是32個字節寬。第二:共享變量不會被頻繁的寫。由於使用追加字節的方式須要處理器讀取更多的字節到高速緩衝區,這自己就會帶來必定的性能消耗,共享變量若是不被頻繁寫的話,鎖的概率也很是小,就不必經過追加字節的方式來避免相互鎖定。

相關文章
相關標籤/搜索