我想在一個進程內運行多個線程。我正在尋找能夠在線程之間傳遞消息的最有效方式。尋找一個最佳的多線程消息隊列
每個線程都有一個共享內存輸入消息緩衝區。其他線程會寫入適當的緩衝區。
消息將具有優先權。我想自己管理這個過程。
沒有進入昂貴的鎖定或同步,最好的方法是什麼?或者是否已經有一個經過驗證的可用庫? (Delphi,C或C#很好)。
我想在一個進程內運行多個線程。我正在尋找能夠在線程之間傳遞消息的最有效方式。尋找一個最佳的多線程消息隊列
每個線程都有一個共享內存輸入消息緩衝區。其他線程會寫入適當的緩衝區。
消息將具有優先權。我想自己管理這個過程。
沒有進入昂貴的鎖定或同步,最好的方法是什麼?或者是否已經有一個經過驗證的可用庫? (Delphi,C或C#很好)。
這是很難得到正確不重複犯了很多錯誤已經爲你:)
由其他人看看Intel Threading Building Blocks - 庫中有幾個精心設計的隊列模板(和其他收藏品),您可以測試並查看哪個最適合您的目的。
如果您要使用多個線程,很難避免同步。幸運的是它不是很難。
對於單個進程,臨界區通常是最佳選擇。這是快速和易於使用。爲了簡單起見,我通常將它包裝在一個類中以處理初始化和清理。
#include <Windows.h>
class CTkCritSec
{
public:
CTkCritSec(void)
{
::InitializeCriticalSection(&m_critSec);
}
~CTkCritSec(void)
{
::DeleteCriticalSection(&m_critSec);
}
void Lock()
{
::EnterCriticalSection(&m_critSec);
}
void Unlock()
{
::LeaveCriticalSection(&m_critSec);
}
private:
CRITICAL_SECTION m_critSec;
};
使用鎖定/解鎖它的「自動鎖定」類可以使它更簡單。
class CTkAutoLock
{
public:
CTkAutoLock(CTkCritSec &lock)
: m_lock(lock)
{
m_lock.Lock();
}
virtual ~CTkAutoLock()
{
m_lock.Unlock();
}
private:
CTkCritSec &m_lock;
};
任何你想鎖定的東西,實例化一個自動鎖定。當功能結束時,它將解鎖。此外,如果有例外,它會自動解鎖(提供異常安全)。
現在你可以做一個簡單的消息隊列進行性病優先級隊列
#include <queue>
#include <deque>
#include <functional>
#include <string>
struct CMsg
{
CMsg(const std::string &s, int n=1)
: sText(s), nPriority(n)
{
}
int nPriority;
std::string sText;
struct Compare : public std::binary_function<bool, const CMsg *, const CMsg *>
{
bool operator() (const CMsg *p0, const CMsg *p1)
{
return p0->nPriority < p1->nPriority;
}
};
};
class CMsgQueue :
private std::priority_queue<CMsg *, std::deque<CMsg *>, CMsg::Compare >
{
public:
void Push(CMsg *pJob)
{
CTkAutoLock lk(m_critSec);
push(pJob);
}
CMsg *Pop()
{
CTkAutoLock lk(m_critSec);
CMsg *pJob(NULL);
if (!Empty())
{
pJob = top();
pop();
}
return pJob;
}
bool Empty()
{
CTkAutoLock lk(m_critSec);
return empty();
}
private:
CTkCritSec m_critSec;
};
的CMSG的內容可以是你喜歡的東西。請注意,CMsgQue從std :: priority_queue繼承私有。這會阻止原始訪問隊列,而不通過我們的(同步)方法。
爲每個線程分配一個這樣的隊列,你就在路上。
免責聲明這裏的代碼被快速打包在一起來說明一個觀點。它可能存在錯誤,需要在用於生產之前進行審查和測試。
謝謝邁克爾! 我看到了一個使用ASM的解決方案,可以抵消任何鎖的需求!我不認爲這在.Net中是可能的。 – IamIC 2010-07-28 15:59:21
@IanC我不明白你怎麼能沒有鎖。我猜想ASM代碼本身就是在執行鎖。如果兩個線程同時嘗試訪問隊列,而沒有鎖定,則會發生不好的事情。 :-(你可以使用Interlocked *()函數來完成自己的鎖定,但通常這並不比使用關鍵部分容易。 – 2010-07-28 16:47:05
我注意到在我的機器上,我可以每秒鎖定和解鎖200萬次。但是使用原子ASM函數,我可以每秒執行超過2000萬次鎖定/解鎖(使用cmpxchg),所以這兩種方法之間必須有顯着的差異。 – IamIC 2010-08-02 15:08:36
謝謝尼古拉:) – IamIC 2010-07-28 04:02:31