2015-05-14 40 views
4

我已經介紹了LMAX和這個美妙的概念,叫做RingBuffer。 所以,人們告訴說,當只寫一個線程的性能比使用多線程寫入環緩衝更好...用單線程寫LMAX

但是我真的不覺得可能只有一個應用程序只使用一個線程寫入環形緩衝區。我真的不明白lmax如何做(如果他們這樣做)。例如,N個不同的交易者在交易中下達訂單,那些都是異步請求,這些請求被轉換爲訂單並放入循環緩衝區,他們如何可能使用一個線程編寫這些請求?

問題1.我可能會錯過某些東西或誤解某些方面,但是如果您有N個併發生產者,它們如何合併爲1而不互相鎖定?

問題2:我記得rxJava可觀察到的物體,在這裏你可以使用N個可觀察物並將它們合併爲1,使用Observable.merge我想知道它是以任何方式阻擋或保持任何鎖嗎?

回答

2

對多線程寫入的RingBuffer的影響是輕微的,但是在非常重的負載下可能是顯着的。

RingBuffer實現包含一個next節點,其中將進行下一個添加。如果只有一個線程正在向環寫入,則該過程總是在最短時間內完成,即buffer[head++] = newData

要處理多線程,同時避免鎖定,你通常會做類似while (!buffer[head++].compareAndSet(null,newValue)){}。這個緊密的循環將繼續執行,而其他線程正在干擾數據的存儲,從而減慢城鎮吞吐量。

請注意,我已經使用了上面的僞代碼,在我的實現here中看看getFree的一個實例。

// Find the next free element and mark it not free. 
    private Node<T> getFree() { 
    Node<T> freeNode = head.get(); 
    int skipped = 0; 
    // Stop when we hit the end of the list 
    // ... or we successfully transit a node from free to not-free. 
    // This is the loop that could cause delays under hight thread activity. 
    while (skipped < capacity && !freeNode.free.compareAndSet(true, false)) { 
     skipped += 1; 
     freeNode = freeNode.next; 
    } 
    // ... 
    } 
+0

因此,對於N個生產者(其中n不是很大)使用它會比在寫入訪問上阻塞更快嗎? – vach

+0

@vach - 是的。任何非阻塞算法都優於使用鎖的算法。 – OldCurmudgeon

+0

我不明白的是LMAX如何在單線程中做到這一點?他們同時得到很多訂單,他們如何讓他們在單線程中獲得鈴聲? 任何想法:)? – vach

2

內部,RxJava的合併採用了系列化結構我稱之爲emitter-loop它採用​​和阻止。

我們的'客戶'使用合併主​​要在吞吐量和延遲不敏感的情況下,或者完全單線程和阻塞並不是真正的問題。

有可能編寫一個非阻塞串行器我呼籲queue-drain但合併不能被配置爲使用它。

如果你願意手動處理生產者和消費者線程,你也可以直接看JCTools'MpscArrayQueue