2014-10-29 32 views
1

我有一個問題,線程A正在從curl回調接收視頻數據並將數據添加到std::deque,而線程B正在讀取數據並從std::deque中讀取並處理它。C++隊列非鎖定

我鎖定std::deque當線程A是將數據添加到它,並且當線程B從中讀取數據鎖定。

一切工作正常,但幾分鐘後,我的捲曲回撥最終停止死亡,沒有接收到更多的視頻數據。
我假設線程B花費的時間太長來處理數據,因此持續時間太長,因此curl回調最終會停止。

有沒有辦法,我可以在C++使用,我沒有添加和讀取的時候將其鎖定任何隊列?

如果需要,我可以發佈我的代碼。

+2

一個簡單的方法可以將指針推到deque上。當你需要處理一個時,只要需要鎖就可以彈出指針。然後在處理數據之前釋放鎖。 (考慮使用'std :: unique_ptr',這樣你就不必手動管理內存了。) – cdhowie 2014-10-29 20:27:03

+1

或者讓讀者有自己的'deque',並且鎖定的時間足夠長,以便將shared deque與shared一。交換將比添加或刪除項目更快。然後閱讀器處理隊列副本中的所有內容,清空它,然後鎖定並再次與共享內容交換。 – 2014-10-29 20:38:21

回答

1

要避免鎖定,可以使用有界無鎖隊列。可以找到這樣的東西:boost::spsc_queue

檢查生產者端的完整隊列還可以停止捲曲線程以避免超載。

4

加速提供無鎖隊列,但他們有一個像只被允許存儲POD類型的限制。

常見的解決方案是爲消費者有自己的隊列對象,開始爲空,而當它包含的工作獲取與共享隊列對象交換。

std::mutex global_queue_mutex; 
std::condition_variable work_available; 
std::deque<Work> global_queue; 

void consumer() 
{ 
    std::deque<Work> local; 
    while (true) 
    { 
    // wait for work to be available and then swap it into local queue 
    { 
     std::unique_lock<std::mutex> lock(global_queue_mutex); 
     work_available.wait(lock, [&]{ return !global_queue.empty(); }); 
     local.swap(global_queue); 
    } 
    for (auto& work : local) 
    { 
     // do work 
    } 
    local.clear(); 
    } 
} 

void producer() 
{ 
    // ... 
    { 
    std::lock_guard<std::mutex> lock(global_queue_mutex); 
    global_queue.push_back(std::move(work)); 
    } 
    work_available.notify_one(); 
    // ... 
} 

消費者只持有足夠長的鎖以檢查工作並進行交換,這將非常快速。生產者只保持足夠長的時間以將單個項目推入隊列。