"Вложенный" scoped_lock
Мой сокращенный, упрощенный класс выглядит следующим образом:
class A
{
public:
// ...
methodA();
methodB();
protected:
mutable boost::mutex m_mutex;
sometype* m_myVar;
}
A::methodA( int someParam )
{
boost::mutex::scoped_lock myLock(m_mutex);
m_myVar->doSomethingElse();
}
A::methodB( int someParam )
{
boost::mutex::scoped_lock myLock(m_mutex);
m_myVar->doSomething();
this->methodA(someParam);
}
Я хотел бы синхронизировать доступ на m_myVar
, При звонке A::methodB()
, поток встречается с одним и тем же мьютексом дважды и, очевидно, блокируется в первой строке A::methodA()
Есть ли способ сделать scoped_lock
не блокировать тот же поток при повторном прохождении?
Конечно, я просто мог позвонить m_mutex.unlock()
, Но это освободило бы другие потоки, ожидающие блокировки, а это совсем не то, что я хочу.
Любая идея?
С наилучшими пожеланиями Тобиас
3 ответа
Это то, что boost::recursive_mutex
так как позволяет получить блокировку одним и тем же потоком без блокировки несколько раз. Используйте это вместо boost::mutex
Есть разные вещи, которые вы можете сделать здесь. Вы можете использовать рекурсивный мьютекс, который может быть получен несколько раз в одном потоке, или вы можете разделить methodA
в приватный метод с реализацией и без блокировок, и публичный метод, который блокирует и затем вызывает приватную реализацию. затем methodB
будет вызывать внутреннюю реализацию, удерживая блокировку. Поскольку метод является частным, вы можете контролировать все его применения и можете гарантировать, что метод реализации вызывается только при удержании блокировки.
Вы можете использовать tryLock в methodA, если попытка не удалась, вы должны получить текущий threadId и продолжить выполнение, только если идентификатор потока совпадает с threadid, который запускает MethodB. В противном случае, если попытка завершится успешно, вы можете продолжить выполнение в обычном режиме.