Проверьте, заблокирован или разблокирован мьютекс pthread (после того, как поток заблокирован)
Мне нужно проверить, заблокирован или разблокирован мьютекс в выражении if, поэтому я проверяю его так:
if(mutex[id] != 2){
/* do stuff */
}
но когда я проверяю его, gcc дает мне следующую ошибку:
error: invalid operands to binary != (have 'ptherad_mutex_t' and 'int')
Итак, как я могу проверить, заблокирован ли мьютекс или нет?
EDIT:
Ключевым компонентом моей проблемы является то, что мои потоки (по дизайну) сами блокируют себя ПОСЛЕ передачи управления другому потоку. Поэтому, когда поток A передает управление потоку B, поток A заблокирован, поток B выполняет некоторые действия, а затем, когда выполняется поток B, он разблокирует поток A.
Проблема заключается в том, что если поток B пытается разблокировать поток A, а поток A еще не завершил блокировку, то вызов разблокировки будет потерян, а поток A останется заблокированным, что вызывает мертвую блокировку.
UPDATE:
Я переделал свою программу, беря предложение caf, но у меня все еще возникают проблемы. Я формовал свою программу в структуру caf, предоставляя лучшее, что могу, но я не могу даже сказать, что вызывает мертвую блокировку... Я создал новый вопрос здесь обращаясь за помощью к моему коду.
Ниже приведена версия версии caf. Я сделал небольшое переупорядочение в функции для потока a, без которой оба потока a и thread b были бы заблокированы при их создании, ожидая условия, которые никогда не могут измениться.
#include <pthread.h>
int run_a = 0;
pthread_mutex_t lock_a = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_a = PTHREAD_COND_INITIALIZER;
int run_b = 0;
pthread_mutex_t lock_b = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_b = PTHREAD_COND_INITIALIZER;
void *a(void *);
void *b(void *);
int main(){
int status;
pthread_t thread_a;
pthread_t thread_b;
pthread_create(&thread_a, NULL, a, (void *)0);
pthread_create(&thread_b, NULL, b, (void *)0);
pthread_join(thread_a, (void **)&status);
pthread_join(thread_b, (void **)&status);
}
/* thread A */
void *a(void *i){
while (1) {
printf("thread A is running\n");
sleep(1);
/* unlock thread B */
pthread_mutex_lock(&lock_b);
run_b = 1;
pthread_cond_signal(&cond_b);
pthread_mutex_unlock(&lock_b);
/* wait for thread A to be runnable */
pthread_mutex_lock(&lock_a);
while (!run_a)
pthread_cond_wait(&cond_a, &lock_a);
run_a = 0;
pthread_mutex_unlock(&lock_a);
}
}
/* thread B */
void *b(void *i){
while (1) {
/* wait for thread B to be runnable */
pthread_mutex_lock(&lock_b);
while (!run_b)
pthread_cond_wait(&cond_b, &lock_b);
run_b = 0;
pthread_mutex_unlock(&lock_b);
printf("thread B is running\n");
sleep(1);
/* unlock thread A */
pthread_mutex_lock(&lock_a);
run_a = 1;
pthread_cond_signal(&cond_a);
pthread_mutex_unlock(&lock_a);
}
}
Ответы
Ответ 1
Мьютексы не являются правильным примитивом для схемы, которую вы хотите реализовать. Вы должны использовать переменные условия:
int run_thread_a = 0;
pthread_mutex_t run_lock_a = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t run_cond_a = PTHREAD_COND_INITIALIZER;
int run_thread_b = 0;
pthread_mutex_t run_lock_b = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t run_cond_b = PTHREAD_COND_INITIALIZER;
/* thread A */
while (1) {
/* Wait for Thread A to be runnable */
pthread_mutex_lock(&run_lock_a);
while (!run_thread_a)
pthread_cond_wait(&run_cond_a, &run_lock_a);
run_thread_a = 0;
pthread_mutex_unlock(&run_lock_a);
/* Do some work */
/* Now wake thread B */
pthread_mutex_lock(&run_lock_b);
run_thread_b = 1;
pthread_cond_signal(&run_cond_b);
pthread_mutex_unlock(&run_lock_b);
}
/* thread B */
while (1) {
/* Wait for Thread B to be runnable */
pthread_mutex_lock(&run_lock_b);
while (!run_thread_b)
pthread_cond_wait(&run_cond_b, &run_lock_b);
run_thread_b = 0;
pthread_mutex_unlock(&run_lock_b);
/* Do some work */
/* Now wake thread A */
pthread_mutex_lock(&run_lock_a);
run_thread_a = 1;
pthread_cond_signal(&run_cond_a);
pthread_mutex_unlock(&run_lock_a);
}
Каждый поток будет блокироваться в pthread_cond_wait()
, пока другой поток не начнет просыпаться. Это не будет заторможен.
Он может быть легко распространен на многие потоки, выделяя один int
, pthread_cond_t
и pthread_mutex_t
для каждого потока.
Ответ 2
Вы можете использовать pthread_mutex_trylock
. Если это удастся, мьютекс был невостребован, и теперь у вас есть его (так что вы должны его отпустить и вернуть "незаслуженно" в вашем случае). В противном случае кто-то держит его.
Я должен подчеркнуть, что "проверить, не является ли мьютекс невостребованным", это очень плохая идея. В этом виде мышления присущи условия расы. Если такая функция сообщит вам в момент времени t
, что блокировка не обнаружена, это абсолютно не говорит о том, приобрел ли какой-либо другой поток блокировку в t+1
.
Если это лучше иллюстрируется примером кода, рассмотрите:
bool held = is_lock_held();
if (!held)
{
// What exactly can you conclude here? Pretty much nothing.
// It was unheld at some point in the past but it might be held
// by the time you got to this point, or by the time you do your
// next instruction...
}
Ответ 3
Вы не можете сравнить pthread_mutex_t с int.
Ты можешь использовать
int pthread_mutex_trylock(pthread_mutex_t *mutex);
чтобы проверить это.