Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding deadlock in case of nested calls when designing thread safe class

I understand I can use a mutex member in a class and lock it inside each method to prevent data race in multithreading environment. However, such method might incur deadlock if there are nested calls in the class's methods, like the add_one() and add_two() in below class. Using different mutex for each method is a workaround. But are there more principled and elegant way to prevent deadlock in the case of nested calls?

class AddClass {
public:
  AddClass& operator=(AddClass const&) = delete; // disable copy-assignment constructor
  AddClass(int val) : base(val) {}
  int add_one() { return ++base; }
  int add_two() { 
    add_one; 
    add_one;
    return base;
  }
private:
  int base;
};
like image 630
ROBOT AI Avatar asked Oct 29 '25 05:10

ROBOT AI


1 Answers

There is std::recursive_mutex exactly for this purpose.

Another approach that avoids overhead incurred by recursive mutex is to separate public synchronized interface from private non-synchronized implementation:

class AddClass {
public:
  AddClass& operator=(AddClass const&) = delete; // disable copy-assignment constructor
  AddClass(int val) : base(val) {}
  int add_one() {
     std::lock_guard<std::mutex> guard{mutex};
     return add_one_impl();
  }
  int add_two() {
     std::lock_guard<std::mutex> guard{mutex};
     return add_two_impl();
  }
private:
  int base;
  std::mutex mutex;
  int add_one_impl() { 
    return ++base;
  }
  int add_two_impl() { 
    add_one_impl(); 
    add_one_impl();
    return base;
  }
};

Note, however, that this is not always possible. For example if you have a method that accepts a callback and calls it while holding the lock, the callback might try to call some other public method of your class, and you are again faced with the double locking attempt.

like image 166
yuri kilochek Avatar answered Oct 30 '25 22:10

yuri kilochek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!