代码之家  ›  专栏  ›  技术社区  ›  user2440195

互斥锁定/解锁顺序

  •  5
  • user2440195  · 技术社区  · 10 年前

    我很感兴趣的是互斥体(不取决于特定语言) 必须 保持锁定/解锁顺序?
    下面是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中运行此代码后(进行了一些更改以使代码不被优化),我总是只在第一个断点处命中。

    2 回复  |  直到 10 年前
        1
  •  5
  •   kraskevich    10 年前

    不,订单没有保证。它恰好在你的机器上(例如,在我的电脑上)以这种方式工作 ok 并非总是正确的)。

        2
  •  1
  •   amchacon    10 年前

    不,订单没有保证。

    您可以尝试使用条件变量:

    #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
      }
    }