簡體   English   中英

線程鎖定互斥鎖的速度比std :: conditional_variable :: wait()快

[英]Threads lock mutex faster than std::conditional_variable::wait()

我正在嘗試了解condition_variables。

我猜我的代碼應該像這樣工作:
1.主鎖
2. main wait()notify <= here鎖已釋放
3.線程鎖定mx
4.線程發送通知
5.線程解鎖MX
6. main wait()完成並鎖定mx

那么,為什么通知后線程鎖定mx的速度比wait()調用的速度快?

#include <iostream>
#include <future>
#include <condition_variable>
#include <vector>

using namespace std::chrono_literals;

std::shared_future<void> ready;

std::mutex finish_mx;
std::condition_variable finish_cv;

int execute(int val, const std::shared_future<void> &ready){
    ready.wait();

    std::lock_guard<std::mutex> lock(finish_mx);
    std::cout<<"Locked: "<<val<<std::endl;
    finish_cv.notify_one();

    return val;
}


int main()
{
    std::promise<void> promise;
    auto shared = promise.get_future().share();

    std::vector<std::future<int>> pool;
    for (int i=0; i<10; ++i){
        auto fut = std::async(std::launch::async, execute, i, std::cref(shared));
        pool.push_back(std::move(fut));
    }

    std::this_thread::sleep_for(100ms);

    std::unique_lock<std::mutex> finish_lock(finish_mx);
    promise.set_value();

    for (int i=0; pool.size() > 0; ++i)
    {
        finish_cv.wait(finish_lock);
        std::cout<<"Notifies: "<<i<<std::endl;

        for (auto it = pool.begin(); it != pool.end(); ++it) {
            auto state = it->wait_for(0ms);
            if (state == std::future_status::ready) {
                pool.erase(it);
                break;
            }
        }
    }
}

示例輸出:

Locked: 6
Locked: 7
Locked: 8
Locked: 9
Locked: 5
Locked: 4
Locked: 3
Locked: 2
Locked: 1
Notifies: 0
Locked: 0
Notifies: 1

編輯

for (int i=0; pool.size() > 0; ++i)
{
    finish_cv.wait(finish_lock);
    std::cout<<"Notifies: "<<i<<std::endl;

    auto it = pool.begin();
    while (it != pool.end()) {
        auto state = it->wait_for(0ms);
        if (state == std::future_status::ready) {
            /* process result */
            it = pool.erase(it);
        } else {
            ++it;
        }
    }
}

這取決於您的操作系統如何調度正在等待獲取互斥鎖的線程。 所有execute線程已經在第一個notify_one之前等待獲取互斥鎖,因此,如果有一個簡單的FIFO隊列在等待鎖定互斥鎖,則它們都在隊列中的main線程之前。 當每個互斥鎖都解鎖互斥鎖時,隊列中的下一個互斥鎖會對其進行鎖定。

這與互斥鎖比條件變量“更快”無關,條件變量必須鎖定相同的互斥鎖以從等待中返回。

一旦將來准備就緒,所有execute線程都將從wait返回,並且所有人都嘗試鎖定互斥鎖,從而加入等待者隊列。 當條件變量開始等待時,互斥鎖將被解鎖,其他線程之一(位於隊列前面的線程)將獲得鎖。 它調用notify_one ,這使條件變量嘗試重新鎖定互斥鎖,從而加入了隊列的后面。 通知線程將互斥鎖解鎖,隊列中的下一個線程將獲得鎖,並調用notify_one (這不會執行任何操作,因為條件變量已被通知並等待鎖定互斥鎖)。 然后,隊列中的下一個線程獲取互斥對象,依此類推。

似乎其中一個execute線程運行得不夠快,無法在第一個notify_one調用之前進入隊列,因此它最終出現在條件變量后面的隊列中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM