我对在C中使用多个互斥锁感到困惑。
int main() {
pthread_t thread1;
char *message1 = "Thread 1";
int r;
pthread_mutex_init(&mutex1, NULL);
pthread_mutex_init(&mutex2, NULL);
pthread_mutex_lock(&mutex1);
r = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
printf("Parent 1\n");
pthread_mutex_lock(&mutex2);
printf("Parent 2\n");
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
pthread_join( thread1, NULL);
printf("Thread 1 returns: %d\n",r);
return 0;
}
void *print_message_function( void *str ) {
pthread_mutex_lock(&mutex1);
char *message;
message = (char *) str;
printf("Child 1 received message: %s \n", message);
pthread_mutex_lock(&mutex2);
printf("child 2\n");
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
return NULL;
}
输出
Parent 1
Parent 2
Child 1 received message: Thread 1
child 2
Thread 1 returns: 0
我想要的是
Parent 1
Child 1 received message: Thread 1
Parent 2
child 2
Thread 1 returns: 0
答案 0 :(得分:5)
当您致电pthread_create
时,您已锁定mutex1
。这意味着调用pthread_mutex_lock(&mutex1);
的每个其他线程都将等待互斥锁被解锁。这就是当您创建第二个线程时发生的情况:mutex1
已被锁定,因此第二个线程无法进入临界区但需要等待互斥锁解锁。这发生在main
函数的末尾。
您需要重新组织代码才能获得所需的输出。
但是,要获得此类结果,您应该检查同步系统,例如semaphores或condition variables;它们将提供更清晰,更简单的线程同步方式 您还可以查看本教程:POSIX Threads Programming
使用信号量的简单解决方案(未经测试,但它应该有效):
#include <stdio.h>
#include <semaphore.h>
sem_t sem1, sem2;
void* f(void* str) {
sem_wait(&sem1);
printf("Child 1 received message: %s \n",(char*)str);
sem_post(&sem2);
sem_wait(&sem1);
printf("Child 2\n");
return NULL;
}
int main (int argc, const char * argv[]) {
pthread_t thread;
char* message = "Thread 1";
int r;
sem_init(&sem1,0,0);
sem_init(&sem2,0,0);
r = pthread_create(&thread, NULL, f, (void*)message);
sem_post(&sem1);
sem_wait(&sem2);
printf("Parent 2\n");
sem_post(&sem1);
pthread_join(thread1, NULL);
printf("Thread 1 returns: %d\n",r);
return 0;
}
答案 1 :(得分:3)
单独的互斥锁不适合执行您想要的那种紧密互锁执行 - 它们的正常用途是保护对共享数据结构的访问。这是因为他们的目的是说“Thing A不应该与Thing B同时发生”,但是他们没有说出Thing A或Thing B是第一次还是第二次发生
您可以使用互斥锁和条件变量,但在这种情况下,您的问题最匹配的是pthreads Barrier对象:
#include <stdio.h>
#include <pthread.h>
pthread_barrier_t barrier;
void *print_message_function( void *str )
{
char *message;
message = (char *) str;
pthread_barrier_wait(&barrier); /* Barrier point 1 */
/* (wait until parent prints first message) */
printf("Child 1 received message: %s \n", message);
pthread_barrier_wait(&barrier); /* Barrier point 2 */
/* (allow parent to proceed and print second message) */
pthread_barrier_wait(&barrier); /* Barrier point 3 */
/* (wait for parent to print second message) */
printf("child 2\n");
return NULL;
}
int main()
{
pthread_t thread1;
char *message1 = "Thread 1";
int r;
pthread_barrier_init(&barrier, NULL, 2);
r = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
printf("Parent 1\n");
pthread_barrier_wait(&barrier); /* Barrier point 1 */
/* (allow child to proceed and print first message) */
pthread_barrier_wait(&barrier); /* Barrier point 2 */
/* (wait for child to print first message) */
printf("Parent 2\n");
pthread_barrier_wait(&barrier); /* Barrier point 3 */
/* (allow child to proceed and print second message) */
pthread_join( thread1, NULL);
/* (wait for child to exit) */
printf("Thread 1 returns: %d\n",r);
return 0;
}
请注意,尝试以这种方式紧密地锁定线程的执行是通常不是 - 实际上,您已经非常努力地确保线程不会并行执行所有,这首先是线程的全部要点。如果你发现自己在一个真实的项目中这样做,那就表明你应该仔细重新思考你的设计。
答案 2 :(得分:2)
我认为您需要尽快解锁mutex1
。您在printf("Parent 2\n");
之后将其解锁,因此thread1仍然处于锁定状态,等待pthread_mutex_lock(&mutex1);
。
当thread1启动时,它的第一步是在等待互斥(名称中的线索)锁定mutex1时锁定。所以它被暂停了。
然后你:
printf("Parent 1\n");
pthread_mutex_lock(&mutex2); <-- lock 2 is unleased but thread one is waiting on mutex1
printf("Parent 2\n");