condition_variable的怪事

今天看了篇介紹condition_variable的文章。因而copy例子到IDE下運行看看,小改了個地方,就出現了讓我百思不得姐的結果。 程序以下:ios

#include <iostream>                // std::cout
#include <thread>                // std::thread
#include <mutex>                // std::mutex, std::unique_lock
#include <condition_variable>    // std::condition_variable

std::mutex mtx; // 全局互斥鎖.
std::condition_variable cv; // 全局條件變量.
bool ready = false; // 全局標誌位.

void do_print_id(int id)
{
    int local = id;
    std::unique_lock <std::mutex> lck(mtx);
    while (!ready) {// 若是標誌位不爲 true, 則等待...
        cv.wait(lck); // 當前線程被阻塞, 當全局標誌位變爲 true 以後,
        local++; //這句到底執行仍是不執行?
    }
    // 線程被喚醒, 繼續往下執行打印線程編號id.
    std::cout << "thread " << id << "\tlocal " << local << std::endl;
}

void go()
{
    std::unique_lock <std::mutex> lck(mtx);
    ready = true; // 設置全局標誌位爲 true.
    cv.notify_all(); // 喚醒全部線程.
    std::cout << "notify_all\n";
}

int main()
{
    const int threads_num = 5; //改變此常數,結果就發生變化了~
    std::thread threads[threads_num];
    // spawn 10 threads:
    for (int i = 0; i < threads_num; ++i)
        threads[i] = std::thread(do_print_id, i);
    
    std::cout << "10 threads ready to race...\n";
    go(); // go!
    
    for (auto & th:threads)
        th.join();
    
    return 0;
}

上述程序中,改變線程數,即
const int threads_num = 5;
結果就發生變化了~ 當threads_num<=5時結果以下:測試

10 threads ready to race... notify_all thread 4 local 4 thread 1 local 2 thread 0 local 0 thread 2 local 2 thread 3 local 3spa

當threads_num>=10,大部分時候程序運行結果以下:線程

10 threads ready to race... notify_all thread 5 local 6 thread 0 local 1 thread 3 local 4 thread 2 local 3 thread 1 local 2 thread 7 local 8 thread 4 local 5 thread 6 local 7 thread 8 local 9 thread 9 local 10code

當threads_num介於5和10之間時,結果在二者之間。編譯器

基本上就是當線程數較小時, cv.wait(lck);後面的那句local++; 不執行;當線程數較大時,又執行了…… 按道理來說,cv.wait(lck);以後線程阻塞,那麼當cv.notify_all();喚醒全部線程以後應該從阻塞的地方開始繼續執行纔對,就應該每次都會執行後面的local++; 爲什麼程序行爲會不一致呢?it

程序的運行環境是Xcode6.1。系統默認編譯器。io

哪位大神幫忙看一下是什麼緣由?編譯

——————————————————後續的分割線———————————————————— 多謝 @BrotherClose 的點撥。經過這個還有幾個發現:thread

  1. 其實第一個const int threads_num = 5時,我貼出來的運行結果仔細看,會發現第二行: thread 1 local 2 已經開始加一了。而我沒仔細看,還覺得全都是相等的…… 若是看出來這個細微的區別的話,也可能會發現線索,找出緣由。
  2. 程序有改進的空間,不將local用id來賦值,而是初始值爲0,那麼結果只有1和0兩個種,一目瞭然,而沒必要比對是否加一。徹底是庸人自擾,自尋煩惱啊。
  3. 爲什麼當啓動線程數量較小時主線程相對優先級較高?而線程數較大時主線程優先級變低?是否和處理器的數量有關呢?主線程也子線程權重差很少,要在多個核心上從新分配,這樣第一次分配到主線程的機會就少了?後來測試,發現cout可能涉及IO操做,會拖慢線程執行,當某線程cout還沒完成時,其餘線程又得到了時間片來執行,結果就反超了。將程序中的log做用的cout都註釋掉,發現當 const int threads_num = 10時,打印結果裏相等的還佔大多數,可見cout的影響仍是蠻大的。
相關文章
相關標籤/搜索