簡體   English   中英

shared_mutex鎖定順序

[英]shared_mutex lock ordering

我的印象是,如果獲得了太多的共享鎖,那么使用c ++ 17的std::shared_mutex實現的多個讀者/單個編寫器模式可能永遠不會放棄唯一鎖。

在挖掘cppreference之后 ,我不確定是這樣的。 特別是:

單個互斥鎖上的所有鎖定和解鎖操作都在一個總訂單中進行

例如,給定shared_mutex上的以下操作,我相信unique_lock可能永遠不會獲取。 假設shared_locks限量的shared_locks ,並且這些鎖在第一個shared_locks發布之前獲取。

shared_lock
shared_lock
shared_lock

unique_lock

shared_lock
[...]
shared_lock

具有以下特點。

{ shared_lock, shared_lock, shared_lock, shared_lock, ..., shared_lock } // never releases

unique_lock

但是,如果我正確理解cppreference,一旦unique_lock嘗試獲取,連續的shared_locks將阻塞,直到unique_lock被釋放。 給出以下線程特征。

{ shared_lock, shared_lock, shared_lock} // simultaneous

unique_lock

{ shared_lock, ..., shared_lock} // waits, then simultaneous

所以我的問題是, std::shared_mutex在共享鎖和唯一鎖之間保持排序? 防止由於獲取了大量的shared_locks而永遠不會獲取unique_locks的情況。

編輯:

這是一個幫助理解問題的代碼示例,為了后人的緣故。 在MSVC 2019上, shared_mutex是安全的,並且根據需要進行排序。 unique_lock確實在“無限”數量的shared_locks之前得到處理。

現在的問題是,這個平台是否依賴?

#include <chrono>
#include <cstdio>
#include <mutex>
#include <shared_mutex>
#include <thread>
#include <vector>

using namespace std::chrono_literals;

std::shared_mutex smtx;

int main(int, char**) {

    std::vector<std::thread> threads;

    auto read_task = [&]() {
        std::shared_lock l{ smtx };
        printf("read\n");
        std::this_thread::sleep_for(1s);
    };

    auto write_task = [&]() {
        std::unique_lock l{ smtx };
        printf("write\n");
        std::this_thread::sleep_for(1s);
    };

    // Create a few reader tasks.
    threads.emplace_back(read_task);
    threads.emplace_back(read_task);
    threads.emplace_back(read_task);


    // Try to lock a unique_lock before read tasks are done.
    std::this_thread::sleep_for(1ms);
    threads.emplace_back(write_task);

    // Then, enque a gazillion read tasks.
    // Will the unique_lock be locked? [drum roll]

    // Would be while(true), 120 should be enough for demo
    for (size_t i = 0; i < 120; ++i) {
        std::this_thread::sleep_for(1ms);
        threads.emplace_back(read_task);
    }

    for (auto& t : threads) {
        t.join();
    }
}

產出:

read
read
read
write
read
...
read

std shared_mutex規范未指定共享鎖的優先級,也不指定唯一鎖。 也沒有任何API可以設置這樣的優先級。 缺乏優先權規范的原始動機之一是存在如此處所解釋Alexander Terekhov算法

第二個動機是解釋shared_mutex中缺少讀寫器優先級策略。 這是由於算法歸功於Alexander Terekhov,它讓操作系統決定下一個獲得鎖定的線程,而不關心是否正在尋找一個獨特的鎖或共享鎖。 這導致完全缺乏讀者或作家的飢餓。 這很公平。

標准規范不需要Alexander Terekhov算法。 然而,至少我希望,這種算法將是首選,因為缺乏規范或API優先於讀者而不是編寫者,反之亦然。

有關Alexander Terekhov算法的更多細節以及一些代碼,這些代碼在此SO答案中展示了它的行為。

暫無
暫無

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

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