Disruptor-NET算法(是一種無鎖算法)需要我們自己實現(xiàn)某一種特定的內存操作的語義以保證算法的正確性。這時我們就需要顯式的使用一些指令來控制內存操作指令的順序以及其可見性定義。這種指令稱為內存柵欄。
成都創(chuàng)新互聯(lián)服務項目包括豐鎮(zhèn)網站建設、豐鎮(zhèn)網站制作、豐鎮(zhèn)網頁制作以及豐鎮(zhèn)網絡營銷策劃等。多年來,我們專注于互聯(lián)網行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網行業(yè)的解決方案,豐鎮(zhèn)網站推廣取得了明顯的社會效益與經濟效益。目前,我們服務的客戶以成都為中心已經輻射到豐鎮(zhèn)省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!
內存一致性模型需要在各種的程序與系統(tǒng)的各個層次上定義內存訪問的行為。在機器碼與的層次上,其定義將影響硬件的設計者以及機器碼開發(fā)人員;而在高級語言層次上,其定義將影響高級語言開發(fā)人員以及編譯器開發(fā)人員和硬件設計人員。即,內存操作的亂序在各個層次都是存在的。這里,所謂的程序的執(zhí)行順序有三種:
(1)程序順序:指在特定CPU上運行的,執(zhí)行內存操作的代碼的順序。這指的是編譯好的程序二進制鏡像中的指令的順序。編譯器并不一定嚴格按照程序的順序進行二進制代碼的編排。編譯器可以按照既定的規(guī)則,在執(zhí)行代碼優(yōu)化的時候打亂指令的執(zhí)行順序,也就是上面說的程序順序。并且,編譯器可以根據(jù)程序的特定行為進行性能優(yōu)化,這種優(yōu)化可能改變算法的形式與算法的執(zhí)行復雜度。(例如將switch轉化為表驅動序列)
(2)執(zhí)行順序:指在CPU上執(zhí)行的獨立的內存相關的代碼執(zhí)行的順序。執(zhí)行順序和程序順序可能不同,這種不同是編譯器和CPU優(yōu)化造成的結果。CPU在執(zhí)行期(Runtime)根據(jù)自己的內存模型(跟編譯器無關)打亂已經編譯好了的指令的順序,以達到程序的優(yōu)化和最大限度的資源利用。
(3)感知順序:指特定的CPU感知到他自身的或者其他CPU對內存進行操作的順序。感知順序和執(zhí)行順序可能還不一樣。這是由于緩存優(yōu)化或者內存優(yōu)化系統(tǒng)造成的。
而最終的共享內存模型的表現(xiàn)形式是由這三種“順序”共同決定的。即從源代碼到最終執(zhí)行進行了至少三個層次上的代碼順序調整,分別是由編譯器和CPU完成的。我們上面提到,這種代碼執(zhí)行順序的改變雖然在單線程程序中不會引發(fā)副作用,但是在多線程程序中,這種作用是不能夠被忽略的,甚至可能造成完全錯誤的結果。因此,在多線程程序中,我們有時需要人為的限制內存執(zhí)行的順序。而這種限制是通過不同層次的內存柵欄完成的。
Thread.MemoryBarrier就是采用了CPU提供的某些特定的指令的內存柵欄,下面是msdn的解釋【http://msdn.microsoft.com/zh-cn/library/vstudio/system.threading.thread.memorybarrier(v=vs.100).aspx】:
Thread.MemoryBarrier: 按如下方式同步內存訪問:執(zhí)行當前線程的處理器在對指令重新排序時,不能采用先執(zhí)行 MemoryBarrier調用之后的內存訪問,再執(zhí)行 MemoryBarrier調用之前的內存訪問的方式。
按照我個人的理解:就是寫完數(shù)據(jù)之后,調用MemoryBarrier,數(shù)據(jù)就會立即刷新,另外在讀取數(shù)據(jù)之前調用MemoryBarrier可以確保讀取的數(shù)據(jù)是最新的,并且處理器對MemoryBarrier的優(yōu)化小心處理。
int _answer; bool _complete; void A() { _answer = 123; Thread.MemoryBarrier(); //在寫完之后,創(chuàng)建內存柵欄 _complete = true; Thread.MemoryBarrier();//在寫完之后,創(chuàng)建內存柵欄 } void B() { Thread.MemoryBarrier();//在讀取之前,創(chuàng)建內存柵欄 if (_complete) { Thread.MemoryBarrier();//在讀取之前,創(chuàng)建內存柵欄 Console.WriteLine(_answer); } }
Disruptor-NET正是通過Thread.MemoryBarrier 實現(xiàn)無鎖和線程安全的內存操作,看下面是他的Atomic的Volatile類對常用數(shù)據(jù)類型的封裝
/// <summary> /// An integer value that may be updated atomically /// </summary> public struct Integer { private int _value; /// <summary> /// Create a new <see cref="Integer"/> with the given initial value. /// </summary> /// <param name="value">Initial value</param> public Integer(int value) { _value = value; } /// <summary> /// Read the value without applying any fence /// </summary> /// <returns>The current value</returns> public int ReadUnfenced() { return _value; } /// <summary> /// Read the value applying acquire fence semantic /// </summary> /// <returns>The current value</returns> public int ReadAcquireFence() { var value = _value; Thread.MemoryBarrier(); return value; } /// <summary> /// Read the value applying full fence semantic /// </summary> /// <returns>The current value</returns> public int ReadFullFence() { var value = _value; Thread.MemoryBarrier(); return value; } /// <summary> /// Read the value applying a compiler only fence, no CPU fence is applied /// </summary> /// <returns>The current value</returns> [MethodImpl(MethodImplOptions.NoOptimization)] public int ReadCompilerOnlyFence() { return _value; } /// <summary> /// Write the value applying release fence semantic /// </summary> /// <param name="newValue">The new value</param> public void WriteReleaseFence(int newValue) { _value = newValue; Thread.MemoryBarrier(); } /// <summary> /// Write the value applying full fence semantic /// </summary> /// <param name="newValue">The new value</param> public void WriteFullFence(int newValue) { _value = newValue; Thread.MemoryBarrier(); } /// <summary> /// Write the value applying a compiler fence only, no CPU fence is applied /// </summary> /// <param name="newValue">The new value</param> [MethodImpl(MethodImplOptions.NoOptimization)] public void WriteCompilerOnlyFence(int newValue) { _value = newValue; } /// <summary> /// Write without applying any fence /// </summary> /// <param name="newValue">The new value</param> public void WriteUnfenced(int newValue) { _value = newValue; } /// <summary> /// Atomically set the value to the given updated value if the current value equals the comparand /// </summary> /// <param name="newValue">The new value</param> /// <param name="comparand">The comparand (expected value)</param> /// <returns></returns> public bool AtomicCompareExchange(int newValue, int comparand) { return Interlocked.CompareExchange(ref _value, newValue, comparand) == comparand; } /// <summary> /// Atomically set the value to the given updated value /// </summary> /// <param name="newValue">The new value</param> /// <returns>The original value</returns> public int AtomicExchange(int newValue) { return Interlocked.Exchange(ref _value, newValue); } /// <summary> /// Atomically add the given value to the current value and return the sum /// </summary> /// <param name="delta">The value to be added</param> /// <returns>The sum of the current value and the given value</returns> public int AtomicAddAndGet(int delta) { return Interlocked.Add(ref _value, delta); } /// <summary> /// Atomically increment the current value and return the new value /// </summary> /// <returns>The incremented value.</returns> public int AtomicIncrementAndGet() { return Interlocked.Increment(ref _value); } /// <summary> /// Atomically increment the current value and return the new value /// </summary> /// <returns>The decremented value.</returns> public int AtomicDecrementAndGet() { return Interlocked.Decrement(ref _value); } /// <summary> /// Returns the string representation of the current value. /// </summary> /// <returns>the string representation of the current value.</returns> public override string ToString() { var value = ReadFullFence(); return value.ToString(); } }
深入淺出多線程系列之八:內存柵欄和volatile 關鍵字
當前題目:Disruptor-NET和內存柵欄
本文鏈接:http://aaarwkj.com/article0/pdiiio.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供App設計、外貿網站建設、移動網站建設、動態(tài)網站、做網站、定制網站
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)