2011-02-27 42 views
0

用下面的代碼:全部內存屏障和ExclusiveReceiverGroup

var dispatcherQueue = new DispatcherQueue(); 

long totalSum = 0; 

Arbiter.Activate(
    dispatcherQueue, 
    Arbiter.Interleave(
     new TeardownReceiverGroup(), 
     new ExclusiveReceiverGroup(
      Arbiter.Receive<ComputationCompleteResult>(
       true, 
       portSet, 
       computationResult => totalSum += computationResult.Result 
      ), 
     new ConcurrentReceiverGroup(
      // Imagine that there is a persistent Receiver registered here 
     ) 
    ) 
); 

我需要生成約totalSum + = computationResult.Result完全內存屏障? ExclusiveReceiverGroup的Receiver註冊中的處理程序將由線程池調用,因爲dispatcherQueue不使用分派器。我讀過線程池爲它所調用的回調生成一個內存屏障,但這是否確保了回調引用本身的新鮮度?

ExclusiveReceiverGroup不會與任何其他代碼同時運行,因此通過calculateResult.Result遞增totalSum不必是原子的。我知道Interlocked.Add隱含地產生了一個完整的柵欄,但我只想看看我是否可以在沒有使用的情況下離開。

這是一個理論問題。實際上我沒有像上面的示例代碼那樣的任何代碼,並且我沒有任何這種代碼的用例。所以,我想避免「使用Interlocked.Add以防萬一」的答案。這更多的是「讓我們學點新東西」的問題。

回答

0

我的理解是,因爲ExclusiveReceiverGroup實際上只能在任何時候執行其委託的單個線程實例,所以不需要(進一步)內存屏障。 ExclusiveReceiverGroup的全部要點是解決共享狀態的有害問題,因此它是專門設計的,因此可以避免鎖定。不管你使用的池/調度器如何。

+0

你說得對,但是如果我們在DispatcherQueue中使用Dispatcher,似乎還是會產生內存障礙。分派器在它創建的線程上調用回調,對此沒有內存屏障gaurantees(我相信)。在這種情況下,我們必須自己生成內存屏障,以確保我們使用的totalSum的值是來自主內存的全新副本。如果我們使用沒有Dispatcher的DispatcherQueue,我們不必生成完整的內存屏障,因爲ThreadPool爲我們做了這些。這有意義嗎? – 2011-03-04 16:54:05