繁体   English   中英

多线程中的执行流程是什么?

[英]What is the flow of execution in Multi-threading?

我在多线程方面遇到了问题。 请考虑以下代码:

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

void* functionA(void*);
void* functionB(void*);


int main()
{   
    pthread_t tid[2];
    pthread_attr_t arg;

    for(int i = 0; i<2; ++i)
    {
        pthread_attr_init(&arg);

        if(i == 0)
        {
            int x = 0;  
            pthread_create(&tid[i], &arg, functionA, (void*)&x);
        }

        else if(i == 1)
        {
            int x = 6;  
            pthread_create(&tid[i], &arg, functionB, (void*)&x);
        }
    }

 // wait for both threads to finish execution...    
 pthread_join(tid[0], NULL);
 pthread_join(tid[1], NULL);

 return 0;
 }


//.........................DEFINATIONS........................

void* functionA(void* x)
{
    int Index = *((int*)x);
    printf("First: %d\n",Index);    //..................... LINE M
}


void* functionB(void* x)
{
    int Index = *((int*)x);
    printf("Second: %d\n",Index);   //....................... LINE N
}

现在我相信functionA将首先开始执行,因为函数A的求助线程将首先在for循环中创建,所以根据我的输出应该是:

  First: 0                         (from Line M)
  Second: 6                        (from Line N)

但实际输出是,

  Second: 6
  First: 6

现在我很惊讶地看到这一点,我不知道发生了什么。 不仅secondFunction首先开始执行,而且两个函数都显示相同的值,即6,这对我来说没有意义。 任何人都可以请你解释一下这里发生了什么???? 提前致谢...

两件事情

1)这里x变量范围仅限于块if。 所以在您的线程函数中,当您访问该指针时,其范围已经消失所以您正在访问线程函数中的非法内存,这是错误的,它将创建未定义的行为。

回应你的一条评论

那么有没有办法代替变量,我可以直接发送一个常数,例如pthread_create(&tid [i],&arg,functionA,6)??

POSIX线程是一个C API。 C不提供像复制构造函数这样的语言工具,因此无法按值复制任何对象。

你需要总是只通过指针传递一些东西。

2)执行线程的优先级是完全操作系统和调度程序依赖,你不能假设这些线程的序列。

你还想在线程之间进行一些同步,然后使用互斥,条件变量等。

您将指向短期局部变量的指针传递到线程中,一旦这些范围退出就会导致未定义的行为。 可能两个线程都看到x的相同地址。

最明显的解决方法是为变量使用更高的范围,并且每个线程都有一个整数数组:

 pthread_t tid[2];
 pthread_attr_t arg;
 int x[2] = { 0, 6 };
 void * (*func[])(void *) = { functionA, functionB };

 for(int i = 0; i < 2; ++i)
 {
     pthread_attr_init(&arg);
     pthread_create(&tid[i], &arg, func[i], &x[i]);
 }

 // wait for both threads to finish execution...    
 pthread_join(tid[0], NULL);
 pthread_join(tid[1], NULL);

这是有效的,因为x数组将通过对pthread_join()的调用。 也不需要int *转换指针, int *自动转换为C中的void *

关于线程开始顺序的假设也是假的,没有这样的保证。

无法保证他们将以何种顺序运行。 创建线程时,操作系统的调度程序将注册新线程并在有时间时运行它。 基于系统上的优先级和其他hings,它可以按任何顺序选择它们,即中断主线程并启动其他线程,或运行主线程直到连接,然后启动任何其他线程。

可能你正在测试多核系统。 那些甚至可能同时并行运行,但由于某种原因,一个或另一个可能更快(可能来自第二个的数据在缓存中,而第一个必须从内存中获取数据?)

长话短说:没有任何保证。

如果您需要特定订单,您可以使用锁(即互斥锁)来强制执行同步,或者您可以设置优先级(请参阅setpriority())或强制实时调度(sched_setscheduler()),但您真的应该了解您的操作系统。

我相信functionA将首先开始执行,因为forA的forcourse线程将首先在for循环中创建

这种假设不正确,这取决于OS控制的线程调度。

如果要查看正确的输出,请在main()函数范围内声明两个变量(在for循环之前)

int x = 0;  
int y = 6;  

并且还要改变

pthread_create(&tid[i], &arg, functionA, (void*)&x);
 pthread_create(&tid[i], &arg, functionB, (void*)&y);

通过这样做,您至少可以获得正确的输出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM