簡體   English   中英

std :: mutex鎖定的順序

[英]Order of std::mutex locking

我很少考慮兩個連續表達式之間發生的事情,在對函數的調用和它的主體的第一個表達式的執行之間,或者在對構造函數的調用和它的初始化程序的執行之間發生的事情。 然后我開始閱讀並發性...

1.)在std::thread的構造函數中連續兩次調用具有相同的可調用函數(例如function,functor,lambda),其主體以std::lock_guard初始化與相同的std::mutex對象開始,是std::lock_guard保證第一個thread構造函數調用對應的線程首先執行受鎖保護的代碼?

2.)如果標准沒有做出保證,那么第二個thread構造函數調用對應的線程是否有理論或實際可能首先執行受保護的代碼? (例如,執行初始化程序或第一個thread構造函數調用的主體期間的系統負載很重)

這是一個全局std::mutex對象m和一個初始化為1的全局unsigned num 函數foo的主體開口括號{std::lock_guard之間只有空格。 main ,有兩個std::thread s t1t2 t1調用線程構造函數。 t2調用第二個線程構造函數。 每個線程都使用指向foo的指針構造。 t1unsigned參數1調用foo t2unsigned參數2調用foo 根據哪個線程首先鎖定mutex ,在兩個線程執行了受鎖保護的代碼之后, num的值將是43 num將等於4 ,如果t1擊敗t2的鎖。 否則, num將等於3 我通過循環並在每個循環結束時將num重置為1來運行100,000次試驗。 (據我所知,結果不是也不應該依賴於哪個線程首先join() 。)

#include <thread>
#include <mutex>
#include <iostream>

std::mutex m;
unsigned short num = 1;

void foo(unsigned short par) {
    std::lock_guard<std::mutex> guard(m);
    if (1 == num)
        num += par;
    else
        num *= par;
}

int main() {
    unsigned count = 0;
    for (unsigned i = 0; i < 100000; ++i) {
        std::thread t1(foo, 1);
        std::thread t2(foo, 2);
        t1.join();
        t2.join();
        if (4 == num) {
            ++count;
        }
        num = 1;
    }
    std::cout << count << std::endl;
}

最后, count等於100000 ,所以事實證明t1每次都贏得比賽。 但這些試驗沒有任何證據。

3.)標准命令“首先調用thread構造函數”是否總是暗示“首先調用傳遞給thread構造函數的callable”?

4.)標准命令“首先調用傳遞給thread構造函數的callable”總是暗示“首先鎖定mutex ”; 假設在callable的主體內,沒有代碼依賴於在std::lock_guard初始化的行之前傳遞給callable的參數? (還排除任何可調用的本地static變量,如調用次數的計數器,可用於故意延遲某些調用。)

  1. 不,標准不保證第一個線程首先獲得鎖定。 基本上,如果需要在線程之間強加和排序,則需要在這些線程之間進行同步。 即使第一個線程首先調用互斥鎖定函數,第二個線程也可以先獲取鎖定。
  2. 絕對。 例如,在生成線程時,您的應用程序可能只有一個核心可用,如果生成的線程在第二個線程生成等待某個東西后決定,則該計划可能決定處理看到的最新線程,即第二個線程。 即使有很多可用內核,第二個線程也有很多原因。
  3. 不,為什么會這樣! 第一步是生成一個線程並繼續。 到第一個函數對象被調用時,第二個線程可以運行並調用其函數對象。
  4. 不會。除非你自己明確地強加它們,否則線程之間沒有排序保證,因為它們會破壞並發的目的。

暫無
暫無

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

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