我想模擬一個系統,其中有多個線程正在生成數據,並且有一個消耗數據的線程。訣竅是我不希望專用線程使用數據,因爲所有線程都在一個池中。相反,我希望其中一個生產者在工作時清空隊列,並在另一個生產者已經清除隊列時收益。多生產者單消費者延遲任務執行
其基本思想是有一個工作隊列和一個處理周圍的鎖。每個生產者將其有效負載推入隊列,然後嘗試來輸入鎖。該嘗試是非阻塞的,並返回true(獲取鎖)或false(該鎖由其他人持有)。
如果獲得了鎖定,那麼該線程將處理隊列中的所有數據,直到其爲空(包括處理期間由其他生產者引入的任何新的有效載荷)。一旦所有工作都被處理完畢,線程就會釋放鎖定並退出。
以下是該算法的C++代碼:
void Process(ITask *task) {
// queue is a thread safe implementation of a regular queue
queue.push(task);
// crit_sec is some handle to a critical section like object
// try_scoped_lock uses RAII to attempt to acquire the lock in the constructor
// if the lock was acquired, it will release the lock in the
// destructor
try_scoped_lock lock(crit_sec);
// See if this thread won the lottery. Prize is doing all of the dishes
if (!lock.Acquired())
return;
// This thread got the lock, so it needs to do the work
ITask *currTask;
while (queue.try_pop(currTask)) {
... execute task ...
}
}
一般這種代碼工作正常,我從來沒有親眼目睹我對下面描述的行爲,但執行讓我感到不安。理由是在線程退出while循環和釋放臨界區之間引入競爭條件。
整個算法依賴於這樣的假設:如果正在保持鎖,則線程正在爲隊列服務。
我基本上是在尋找啓蒙的2個問題:
- 我是正確,有作爲描述的競態條件(獎金爲其他種族)
- 是否有實現這種機制的標準模式是是高性能的,不會引入競爭條件?
try_pop_or_unlock方法實際上是一個非常有吸引力的想法。我將如何去做這個函數原子? – Mranz 2013-02-28 23:48:59
你是否實現了'queue'?一個簡單的線程安全'隊列'只需要一個'mutex',在這種情況下,只要解鎖傳入的'lock',同時在'queue'爲空時仍然持有'mutex'。對於更加奇特的線程安全'隊列',事情變得更加困難。 – Yakk 2013-02-28 23:51:30
不幸的是,這個實現是後者。 – Mranz 2013-02-28 23:52:34