我试图构建一个程序,该程序应创建线程并为每个线程分配一个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;
}
答案 0 :(得分:1)
该代码将同一局部变量的地址传递给所有线程。同时,此变量由主线程更新。
而是将其按值强制传递给void*
。
修复:
pthread_create(&threadID[indx], NULL, Print, (void*)indx)
// ...
printf("%d from thread\n", (int)_indx);
现在,由于线程之间没有共享数据,因此可以删除该互斥锁。
答案 1 :(得分:1)
尽管存在程序错误的所有问题,pthread互斥锁仅提供 mut ual ex ,但不能保证调度顺序。这是互斥体实现的典型代表。类似地,pthread_create()
仅创建和启动线程。它并不能保证调度顺序,例如,可以假设线程以创建时的相同顺序到达pthread_mutex_lock()
调用。
总体而言,如果您想根据线程的某些特征订购线程活动,则必须自己进行管理。您需要保持对线程转向的感觉,并提供一种足以在线程到达时通知线程的机制。在某些情况下,请谨慎使用信号量而不是互斥量。但是,更通用的解决方案是将条件变量与您的互斥锁一起使用,并使用一些共享变量来指示当前轮到谁了。
答案 2 :(得分:0)
在for循环中创建的所有线程具有不同的 indx 值。由于存在操作系统调度程序,因此您无法确定将运行哪个线程。因此,根据调度程序的随机性,打印的值是随机的。父线程中运行的第二个for循环将在创建子线程后立即运行。再次,调度程序决定下一步应运行什么线程的顺序。
每个操作系统都应有一个中断(至少主要操作系统有一个)。在父线程中运行for循环时,可能会发生中断并使调度程序决定要运行哪个线程。因此,在父for循环中打印的数字是随机打印的,因为所有线程都是“并行运行”的。
加入线程意味着等待线程。如果要确保按时间顺序在父for循环中打印所有数字,而又不让子线程中断它,则将for-loop部分重新定位在加入线程之后。