Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is std::mutex recursive (ie non-reentrant)?

Tags:

c++

c++11

Test environment: Ubuntu 18.04.3 LTS g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0.

Can std::mutex be reentrant? Why does the following test code 1 pass?

code1:

#include <iostream>
#include <mutex>

std::mutex g_mtx4val;
int g_val = 5;

void test() {
  std::lock_guard<std::mutex> lck(g_mtx4val);
  std::cout << "g_val=" << g_val << std::endl;
  if (g_val > 0) {
    --g_val;
    test();
  }
}

int main() {
  test();

  std::cout << "done ...." << std::endl;
  return 0;
}
peanut@peanut:~/demo$ g++ test.cpp 
peanut@peanut:~/demo$ ./a.out 
g_val=5
g_val=4
g_val=3
g_val=2
g_val=1
g_val=0
done ...

code2:

// Same code 1

int main() {
  std::thread t1(test);
  t1.join();

  std::cout << "done ...." << std::endl;
  return 0;
}
peanut@peanut:~/demo$ g++ test2.cpp -lpthread
peanut@peanut:~/demo$ ./a.out 
g_val=5
^C
peanut@peanut:~/demo$ 

code2 has a deadlock. Why code1 can pass the test?

like image 206
lilucpp Avatar asked Oct 28 '25 04:10

lilucpp


1 Answers

From the documentation page:

mutex offers exclusive, non-recursive ownership semantics

So the answer to the question in the title is no.

Can std::mutex be reentrant?

No, but if you want a recursive mutex, the std::recursive_mutex class provides that functionality.

Why does the following test code 1 pass?

What behavior were you expecting to see? The std::mutex documentation page simply says:

A calling thread must not own the mutex prior to calling lock or try_lock.

... it doesn't say what will happen if the calling thread breaks the above rule; which means that a program that breaks the rule may "appear to work", but even so is still incorrect and buggy.

like image 91
Jeremy Friesner Avatar answered Oct 29 '25 18:10

Jeremy Friesner