2015-02-23 156 views
3

我很感興趣互斥鎖(不取決於特定語言)必須是保持鎖定/解鎖的順序?
這裏是例如C++代碼:互斥鎖/解鎖命令

std::mutex testVecMtx; 
std::vector<int> testVec; 

void testPush(int v){ 
    std::lock_guard<std::mutex> lk(testVecMtx); 

    if (testVec.empty()){ 
    // wait some time to get more threads waiting on testVecMtx 
    std::this_thread::sleep_for(std::chrono::milliseconds(3000)); 
    } 

    testVec.push_back(v); 
} 

void Main_TEST(){ 
    std::list<std::thread> thList; 

    for (int i = 0; i < 1000; i++){ 
    thList.push_front(std::thread(testPush, i)); 
    } 

    for (auto &i : thList){ 
    if (i.joinable()){ 
     i.join(); 
    } 
    } 

    bool ok = true; 

    for (int i = 0; i < (testVec.size() - 1) && ok; i++){ 
    ok = testVec[i + 1] - testVec[i] == 1; 
    } 

    if (ok){ 
    int stop = 243; // 1st breaking point here... 
    } 
    else{ 
    int stop = 432; // ...and 2nd here 
    } 
} 

在VS2013中調試和發佈serveral的時間運行該代碼(含部分變更以獲得不優化掉的代碼)模式,我總是隻命中1日斷點之後。

回答

4

不,沒有關於訂單的保證。它恰好在你的機器上以這種方式工作(例如,我的電腦ok並非總是如此)。

+0

它不可靠地工作在Windows下這樣一來,無論是。從[MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684266.aspx):「不要採用先入先出(FIFO)的順序。因爲內核模式的APC可以改變等待順序。「在OP的測試中碰巧沒有這樣的事件。 – Wintermute 2015-02-23 22:03:01

+0

另外它非常普通(如果沒有發生,那麼通常很奇怪)調試器的交互對事件的排序有重要影響。您可能會在調試器中獲得一致的順序,但順序不同,順序也可能不一致。 – Persixty 2015-02-23 22:04:50

+0

你是否在計算機上運行了這個程序,並得到一個確定不正確的場景? – thang 2015-02-23 22:13:45

1

不,沒有關於訂單的保證。

您可以使用條件變量嘗試:

#include <thread> 
#include <vector> 
#include <array> 
#include <list> 
#include <mutex> 
#include <condition_variable> 

const int MAX = 100; //*** 
std::mutex testVecMtx; 
std::vector<int> testVec; 
std::array<std::condition_variable,MAX+1> Notifications; //*** 
int Current = 0; //*** 

void testPush(int v){ 
    std::unique_lock<std::mutex> lk(testVecMtx); 
    while (v != Current){ 
    Notifications[v].wait(lk); 
    } 

    testVec.push_back(v); 
    Current++; 

    if (v != MAX) 
    Notifications[v+1].notify_all(); 
} 

int main(){ 
    std::list<std::thread> thList; 

    for (int i = 0; i < MAX; i++){ 
    thList.push_front(std::thread(testPush,i)); 
    } 

    for (auto &i : thList){ 
     i.join(); 
    } 

    bool ok = true; 

    for (int i = 0; i < (testVec.size() - 1) && ok ;i++){ 
    ok = (testVec[i + 1] - testVec[i]) == 1; 

    } 

    if (ok){ 
    int stop = 243; // 1st breaking point here... 
// std::cout<<"Ok"<<std::endl; 
    } 
    else{ 
    int stop = 432; // ...and 2nd here 
    } 
}