Pthreads- 1 замок, 2 разблокировки - PullRequest
2 голосов
/ 12 августа 2010

Если я правильно понимаю, то foo1 () не может разблокировать & private_value_. В результате, thread_mutex_lock в foo2 () не работает, так как foo1 () никогда не освобождает его.

Каковы другие последствия?

int main ( ... )

foo1();
foo2();

return 0;
}

foo1()
{
 pthread_mutex_lock(&private_value_);
 do something 
 // no unlock!
}

foo2()
{
 pthread_mutex_lock(&private_value_)
 do something
 pthread_mutex_unlock(&private_value_);
}

Ответы [ 8 ]

5 голосов
/ 12 августа 2010

Кажется, здесь есть некоторая путаница между тем, как программа должна быть написана , и тем, как программа, как написано в данный момент, будет вести себя .

Этот код вызовет тупик, и это не означает, что с мьютексами что-то не так. Они работают точно так, как они должны: если вы попытаетесь повторно получить нерекурсивный мьютекс, который уже заблокирован, ваш код будет блокироваться до тех пор, пока мьютекс не будет разблокирован. Вот как это должно работать.

Поскольку этот код является однопоточным, блокировка в foo2 никогда не закончится, и поэтому ваша программа заблокируется и не будет прогрессировать. Скорее всего, это не то, как программа должна работать (потому что это не очень полезная программа в этом смысле). Ошибка не в том, как работают мьютексы, а в том, как программист решил использовать их. Программист должен поставить вызов разблокировки в конце foo1.

4 голосов
/ 12 августа 2010

Мьютекс работает нормально.Он делает то, что должен делать.Поток будет блокироваться после выхода из foo1 (), пока мьютекс не будет получен из foo2.

1 голос
/ 12 августа 2010

Чтобы ответить на вопрос:

Других последствий, кроме тупика, нет (поскольку ваш пример однопоточный и синхронные вызовы) ..

1 голос
/ 12 августа 2010

Нет, это не обязательно блокировать.Все зависит от вашей private_value_ переменной.pthread_mutex_t может показывать другое поведение в соответствии со свойствами, которые были установлены при инициализации переменнойСмотри http://opengroup.org/onlinepubs/007908775/xsh/pthread_mutex_lock.html

1 голос
/ 12 августа 2010

Это ошибка, если блокировка взята на мьютекс, и ничто никогда не снимает блокировку.

Однако это не обязательно означает, что foo1() должен снять блокировку, но что-то должно.

Существуют шаблоны, в которых одна функция получает блокировку, а другая снимает ее. Но вы должны позаботиться о том, чтобы эти более сложные шаблоны обработки мьютексов были правильно закодированы. Возможно, вы смотрите на пример этого (и вычеркнутый фрагмент в вопросе не включает в себя эту дополнительную сложность).

И, как упомянул Нейл Баттерворт в комментарии, в C ++ существует множество ситуаций, когда мьютекс будет управляться классом RAII, поэтому блокировка будет снята автоматически, когда объект 'lock manager' будет уничтожен (часто выходя из области видимости). В этом случае может быть неочевидно, что блокировка снята, поскольку это делается как побочный эффект переменной, просто выходящей из области видимости.

1 голос
/ 12 августа 2010

Вот почему люди переходят на языки, которые предлагают решения на основе контекста, такие как C ++ и RAII. Мьютекс работает как положено, но автор первой функции забыл небольшой вызов, и теперь приложение останавливается.

0 голосов
/ 01 апреля 2011

Поведение этого кода зависит от типа мьютекса:

  • По умолчанию: неопределенное поведение (блокировка уже заблокированного мьютекса).
  • Обычный: тупик (блокировкауже заблокированный мьютекс).
  • Рекурсивно: работает, но оставляет мьютекс заблокированным (так как он заблокирован дважды, но разблокирован только один раз).
  • Проверка ошибок: полностью работает и разблокирует мьютекс вконец (второй вызов блокировки завершается неудачно с EDEADLK, а возвращаемое значение ошибки игнорируется вызывающей стороной).
0 голосов
/ 12 августа 2010

Если вызывается только foo2, все будет работать нормально. Если вызывается foo1, тогда, если вызывается foo2 или любая другая функция, для которой требуется мьютекс, он будет заблокирован навсегда.

...