1. 程式人生 > >C/C++ 執行緒安全佇列

C/C++ 執行緒安全佇列

一、簡介

執行緒安全是一個比較嚴肅的問題,如果處理不好,可能導致資料被破壞,程式崩潰等問題,如何來處理多執行緒的併發問題?在windows平臺有相應的api給你用於控制併發,如互斥鎖,訊號量,事件,臨界區等,定要熟練掌握,當然現在STL庫已強大到相容不同的硬體系統了,當然對於winApi同步可以看這裡:
互斥鎖,訊號量,事件,臨界區詳情

二、分析安全原理

基於conditon_variable類實現執行緒安全,先來看看它有什麼API使

wait阻塞自己,等待喚醒

wait_for阻塞自己,等待喚醒,最多等待一段時間

wait_until阻塞自己,等待喚醒,最多等待到某個時間點

notify_one 喚醒一個等待在這個條件變數上的執行緒

notify_all 喚醒所有等待在這個條件變數上的執行緒

這個有點類似的於event,想讓某處導通就直接setEvent,
某博主的關於condition_variable比較詳細的講解:點此

三、上佇列程式碼

template<typename T> class ThreadSafe_Queue
{
private:
    mutable mutex m_mut;
    queue<T> m_queue;
    condition_variable m_data_cond;
public:
    ThreadSafe_Queue() {}
    ThreadSafe_Queue(const ThreadSafe_Queue&) = delete
; void push(T data) { lock_guard<mutex> lg(m_mut); m_queue.push(data); m_data_cond.notify_one(); } void WaitPop(T&t) { unique_lock<mutex> ul(m_mut); m_data_cond.wait(ul, [this] {return !m_queue.empty(); }); t = m_queue.front(); m_queue.pop(); } shared_ptr
<T> WaitPop() { unique_lock<mutex> ul(m_mut); m_data_cond.wait(ul, [this] {return !m_queue.empty(); }); shared_ptr<T> res(make_shared<T>(m_queue.front())); m_queue.pop(); return res; } bool TryPop(T &t) { lock_guard<mutex> lg(m_mut); if (m_queue.empty()) return false; t = m_queue.front(); m_queue.pop(); return true; } shared_ptr<T> TryPop() { lock_guard<mutex> lg(m_mut); if (m_queue.empty()) return shared_ptr<T>(); shared_ptr<T> res(make_shared<T>(m_queue.front())); m_queue.pop(); return res; } bool IsEmpty() { lock_guard<mutex> lg(m_mut); return m_queue.empty(); } };

四、一個小例子

開了兩個執行緒,用於測試執行緒佇列是否安全,thread_Fuc2用於插入資料,thread_Fuc用於出隊操作,經過測試,達到了安全。

ThreadSafe_Queue<int> g_queue;
int g_index = 10;

void thread_Fuc()
{
    cout << "thread_fuc1 start\n";
    while (true)
    {
        int value=0;
        g_queue.WaitPop(value);
        printf("wait_and_pop done! value=%d  thread id:%d\n",value,GetCurrentThreadId());
    }
}

void thread_Fuc2()
{
    cout << "thread_fuc2 start\n";
    while (true)
    {
        Sleep(1000);
        g_index++;
        g_queue.push(g_index);
    }
}

int main()
{
    thread thd(thread_Fuc);
    thd.detach();

    thread thd2(thread_Fuc2);
    thd2.detach();

    int a;
    while (cin >> a){;}
    return 0;
}

測試圖:
這裡寫圖片描述