如何在 C 中使用互斥体

发布于 2024-12-03 10:39:48 字数 1299 浏览 0 评论 0原文

我对 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

I am confused about use of multiple mutexes in 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;
}

output is

Parent 1
Parent 2
Child 1 received message: Thread 1 
child 2
Thread 1 returns: 0

what i want is

Parent 1
Child 1 received message: Thread 1 
Parent 2
child 2
Thread 1 returns: 0

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

江城子 2024-12-10 10:39:48

当您调用pthread_create时,您已经锁定了mutex1。这意味着调用 pthread_mutex_lock(&mutex1); 的每个其他线程都将等待互斥体解锁。这就是当您创建第二个线程时发生的情况:互斥体 1 已经被锁定,因此第二个线程无法进入临界区,而是需要等待互斥体被解锁。这发生在 main 函数的末尾。

您需要重新组织代码才能获得所需的输出。

但是,要获得这样的结果,您应该检查同步系统,例如信号量 或 条件变量;它们将提供一种更清晰、更简单的线程同步方法。
您还可以查看本教程: POSIX 线程编程


使用信号量的简单解决方案(未经测试,但它应该有效):

#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;
}

When you call pthread_create you have already locked mutex1. That means that every other thread that calls pthread_mutex_lock(&mutex1); will wait for the mutex to be unlocked. That is what happen when you create a second thread: mutex1 is already locked, so the second thread cannot enter the critical section but need to wait for the mutex to be unlocked. That happens at the end of the main function.

You'll need to reorganize your code to get the output you desire.

However, to obtain such a result you should check synchronization systems, such semaphores or condition variables; they will provide a clearer and easier way to synchronize threads.
You may also check this tutorial: POSIX Threads Programming


A simple solution using semaphores (not tested, but it should work):

#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;
}
神经大条 2024-12-10 10:39:48

互斥体本身并不适合执行您想要的那种紧密互锁的执行 - 它们的正常用途是保护对共享数据结构的访问。这是因为它们的目的是说“事情 A 不应该与事情 B 同时发生”,但它们没有说明事情 A 或事情 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;
}

请注意,通常不尝试以这种方式紧密互锁线程的执行 -实际上,您已经煞费苦心地确保线程根本不会并行执行,这首先就是线程的全部意义。如果您发现自己在实际项目中这样做,则表明您应该仔细重新考虑您的设计。

Mutexes alone aren't suitable for performing the kind of closely-interlocked execution that you want - their normal use is for protecting access to a shared data structure. This is because they're designed for saying "Thing A shouldn't happen at the same time as Thing B", but they don't say anything about whether Thing A or Thing B happens first or second.

You could use mutexes and condition variables, but in this case your problem is most closely matched by a pthreads Barrier object:

#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;
}

Note that it is not usual to try to tightly interlock the execution of threads in this way - really, you've gone to great pains to ensure that the threads don't execute in parallel at all, which is the whole point of threads in the first place. If you find yourself doing this in a real project, it's a sign that you ought to carefully re-think your design.

因为看清所以看轻 2024-12-10 10:39:48

我认为您需要尽快解锁 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");

I think you need to unlock mutex1 sooner. You unlock it after the printf("Parent 2\n"); so thread1 is still locked waiting for pthread_mutex_lock(&mutex1);.

When thread1 starts it's first step is to lock while it waits for mutual exclusion (clue's in the name) lock on mutex1. So it's paused.

Then you :

    printf("Parent 1\n");

    pthread_mutex_lock(&mutex2); <-- lock 2 is unleased but thread one is waiting on mutex1
    printf("Parent 2\n");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文