Отвечая на ваши вопросы,
- Если
main
дважды попытается заблокировать lock[0]
, он должен зайти в тупик.
Да, это будет,Если вы не используете рекурсивные мьютексы, но тогда ваш дочерний поток никогда не сможет заблокировать мьютекс, поскольку main
всегда будет блокировать его.
extra
разблокировка lock[0]
, которая была заблокирована главным, должна иметь неопределенное поведение.
Согласно документации POSIX для pthread_mutex_unlock()
, этоявляется неопределенным поведением для ненадежного мьютекса NORMAL
и .Однако мьютекс DEFAULT
не обязательно должен быть NORMAL
и не устойчивым, поэтому есть следующее предупреждение:
Если тип мьютекса равен PTHREAD_MUTEX_DEFAULT
, поведение pthread_mutex_lock()
[и pthread_mutex_unlock()
] может соответствовать одному из трех других стандартных типов мьютекса, как описано в таблице выше.Если он не соответствует ни одному из этих трех, поведение не определено для отмеченных случаев.
(Обратите внимание на мое добавление pthread_mutex_unlock()
. Таблица поведения мьютекса четко показывает, что поведение разблокировки дляне владелец различается в разных типах мьютексов и даже использует один и тот же знак «кинжал» в столбце «Разблокировать, когда не владелец», который используется в столбце «Переблокировать», а знак «кинжал» относится к цитируемой сноске.)
Надежный мьютекс NORMAL
, ERRORCHECK
или RECURSIVE
вернет ошибку, если не владеющий поток попытается разблокировать его, и мьютекс останется заблокированным.
ПрощеРешение состоит в том, чтобы использовать пару семафоров (в следующем коде намеренно отсутствует проверка ошибок вместе с пустыми строками, которые в противном случае повысили бы читаемость для устранения / уменьшения любой вертикальной полосы прокрутки):
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
sem_t main_sem;
sem_t child_sem;
void *child( void *arg )
{
for ( ;; )
{
sem_wait( &child_sem );
sleep( 2 );
sem_post( &main_sem );
}
return( NULL );
}
int main( int argc, char **argv )
{
pthread_t child_tid;
sem_init( &main_sem, 0, 0 );
sem_init( &child_sem, 0, 0 );
pthread_create( &child_tid, NULL, child, NULL );
int x = 0;
for ( ;; )
{
// tell the child thread to go
sem_post( &child_sem );
// wait for the child thread to finish one iteration
sem_wait( &main_sem );
x++;
printf("%d\n", x);
}
pthread_join( child_tid, NULL );
}