具有相互资源互斥的多线程程序[重复]

问题描述 投票:0回答:3

这个问题在这里已有答案:

我试图构建一个程序,它应该创建线程并为每个程序分配一个Print函数,而主进程应该直接使用printf函数。

首先,我没有任何同步手段,并期望获得随机输出。后来我尝试将一个互斥锁添加到Print函数中,该函数被分配给线程,并且期望获得按时间顺序输出,但似乎互斥锁对输出没有影响。

我是否应该在主进程中的printf函数上使用互斥锁?

提前致谢

我的代码:

#include <stdio.h>
#include <pthread.h>
#include <errno.h>

pthread_t threadID[20];
pthread_mutex_t lock;

void* Print(void* _num);

int main(void)
{
    int num = 20, indx = 0, k = 0;

    if (pthread_mutex_init(&lock, NULL))
    {
        perror("err pthread_mutex_init\n");
        return errno;
    }

    for (; indx < num; ++indx)
    {
        if (pthread_create(&threadID[indx], NULL, Print, &indx))
        {
            perror("err pthread_create\n");
            return errno;   
        }
    }

    for (; k < num; ++k)
    {
        printf("%d from main\n", k);
    }

    indx = 0; 

    for (; indx < num; ++indx)
    {
        if (pthread_join(threadID[indx], NULL))
        {
            perror("err pthread_join\n");
            return errno;   
        }
    }

    pthread_mutex_destroy(&lock);

    return 0;
}


void* Print(void* _indx)
{
    pthread_mutex_lock(&lock);

    printf("%d from thread\n", *(int*)_indx);

    pthread_mutex_unlock(&lock);

    return NULL;
}
c multithreading pthreads mutex
3个回答
1
投票

尽管有程序错误的所有问题,但是pthreads互斥锁只提供互斥,而不是任何调度顺序的保证。这是互斥实现的典型。同样,pthread_create()只创建和启动线程;它没有对调度顺序做出任何保证,例如证明线程以与创建它们相同的顺序到达pthread_mutex_lock()调用的假设。

总的来说,如果你想根据线程的某些特性来订购线程活动,那么你必须自己管理它。你需要保持一个线程转向的感觉,并提供一个足以在线程到达时发出线程通知的机制。在某些情况下,您可以通过使用信号量而不是互斥量来做到这一点。然而,更通用的解决方案是将条件变量与您的互斥锁一起使用,以及一些共享变量用于指示当前是谁。


1
投票

代码将相同局部变量的地址传递给所有线程。同时,该变量由主线程更新。

而是通过值转换为void*

固定:

pthread_create(&threadID[indx], NULL, Print, (void*)indx)
// ...
printf("%d from thread\n", (int)_indx);

现在,由于线程之间没有共享数据,您可以删除该互斥锁。


0
投票

在for循环中创建的所有线程都具有不同的indx值。由于操作系统调度程序,您永远无法确定将运行哪个线程。因此,打印的值是随机的,取决于调度程序的随机性。父线程中的第二个for循环运行将在创建子线程后立即运行。同样,调度程序决定接下来应运行的线程的顺序。

每个操作系统都应该有一个中断(至少主要操作系统有)。在父线程中运行for循环时,可能会发生中断并让调度程序决定运行哪个线程。因此,在父for循环中打印的数字是随机打印的,因为所有线程都“同时”运行。

加入线程意味着等待一个线程。如果要确保按时间顺序打印父级for循环中的所有数字,而不让子线程中断它,则将for-loop部分重新定位到线程加入之后。

© www.soinside.com 2019 - 2024. All rights reserved.