互斥lock/unlock顺序

Mutex lock/unlock order

我很感兴趣是否互斥量(不依赖于特定语言)必须保持lock/unlock的顺序?
这是示例 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 中 运行 这段代码在 Debug 和 Release 模式中多次运行(有一些更改以使代码未优化)模式后,我总是只在第一个断点处被命中。

不,无法保证顺序。它恰好在你的机器上以这种方式工作(例如,在我的电脑上 ok 并不总是正确的)。

不,不保证顺序。

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

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