簡體   English   中英

什么是同步此事件實現的最佳方法

[英]What's the best way to synchronize this event implementation

這是我嘗試實現C ++事件。

class Event{
    typedef std::tr1::function<void( int& )> CallbackFunction;
    std::list< CallbackFunction > m_handlers;

    template<class M>
    void AddHandler(M& thisPtr, void typename (M::*callback)(int&)) 
    {           
        CallbackFunction bound = std::tr1::bind(callback, &thisPtr, _1);
        m_handlers.push_back(bound);
    }

    void operator()(int& eventArg) 
    { 
        iterate over list...
        (*iter)(eventArg);

    }}

這里的麻煩是線程安全。 如果同時調用AddHandleroperator() ,事情可能會中斷。

同步這個的最佳方法是什么? 使用互斥鎖可能會降低性能。 我想知道在這種情況下boost :: signals或C#事件幕后會發生什么。

首先,在您將任何實施可能性視為“快速”不足之前,您需要確定實際的性能要求。 您是否會每秒觸發這些事件數千次? 如果你是,那么你是否真的需要一直在處理程序容器中添加處理程序。

如果這兩個問題的答案出於某種原因實際上是“是”,那么您可能需要調查無鎖容器。 這意味着構建自己的容器而不是能夠使用stl列表。 無鎖容器將使用原子內在函數(例如,在Windows中的InterlockedCompareExchange)以原子方式確定列表的末尾是否為NULL或其他。 然后,他們將使用類似的內在實際附加到列表中。 如果多個線程嘗試同時添加處理程序,則會發生其他復雜情況。

然而,在多核機器和指令重新排序等等的世界中,這些方法可能充滿危險。 我個人使用的事件系統與你描述的不同,我將它用於關鍵部分(至少在Windows中非常有效),而且我沒有遇到性能問題。 但另一方面,通過事件系統發送的任何信息都不會超過20Hz左右。

與任何與績效相關的問題一樣,答案總是基於另一個問題的答案; 你究竟在哪里需要你的表現?

互斥是你正在尋找的。 如果每個事件都有自己的互斥鎖,我不會太擔心性能; 原因在於,除非您在處理事件期間添加了大量處理程序,否則互斥體不太可能會出現爭用並使您放慢速度。

但是,如果您有多個線程在同一對象上調用operator()方法,則此互斥鎖可能會出現問題。 但是沒有它,你怎么能確保以線程安全的方式調用你的回調呢? (我注意到你傳入一個整數引用並返回void,所以我假設這些不是可重入的處理程序。)

編輯:你的評論非常好的問題。 說實話,我從未考慮過互斥是否以同步方式使用時有很多開銷。 所以我把這個小測試放在一起。


#include <stdio.h>
#include <pthread.h>

#define USE_PTHREAD_MUTEX 1

int main(int argc, char * argv[]) {

pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);

long useless_number = 0;
long counter;

  for(counter = 0; counter < 100000000; counter++) {
    #if USE_PTHREAD_MUTEX
    pthread_mutex_lock(&mutex);
    #endif
    useless_number += rand();

    #if USE_PTHREAD_MUTEX
    pthread_mutex_unlock(&mutex);
    #endif
  }

  printf("%ld\n", useless_number);

}

我在我的系統上運行了這個並獲得了以下運行時。

使用USE_PTHREAD_MUTEX 0時,平均運行時間為1.2秒。

使用USE_PTHREAD_MUTEX 1時,平均運行時間為2.8秒。

因此,回答你的問題,肯定有開銷。 你的旅費可能會改變。 此外,如果多個線程競爭訪問資源,則必須花費更多時間來阻止。 此外,在純粹的同步上下文中,與等待互斥鎖進行鎖定/解鎖相比,訪問共享資源的時間可能更長。 也就是說,與這些東西相比,互斥邏輯本身的開銷可能微不足道。

如果list真的是你的類,那么由於它的性質,你不需要每次訪問它時都鎖定。 您將鎖定互斥鎖以發布到列表的末尾,並且當您認為可能已到達結束時也會鎖定。

您應該保留類中處理程序數量的計數,當您即將開始迭代時,您可以愉快地迭代而不會鎖定,直到您達到此數字。

如果將要刪除處理程序,那么您有更多的線程爭用問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM