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

C 多线程中的执行流程是什么?,c,multithreading,pthreads,C,Multithreading,Pthreads,我在多线程方面面临一个问题。请考虑以下代码: #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

我在多线程方面面临一个问题。请考虑以下代码:

#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
}
但实际产出是,

  Second: 6
  First: 6
现在我真的很惊讶看到这一点,我不知道发生了什么。不仅secondFunction首先开始执行,而且两个函数都显示相同的值,即6,这对我来说没有意义。谁能解释一下这里发生了什么事吗????
先谢谢你

您正在将指向短期局部变量的指针传递到线程中,一旦这些作用域退出,就会导致未定义的行为。可能两个线程看到的
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);
pthread_t tid[2];
pthread_attr_t arg;
int x[2]={0,6};
void*(*func[])(void*)={functionA,functionab};
对于(int i=0;i<2;++i)
{
pthread_attr_init(&arg);
pthread_create(&tid[i]、&arg、func[i]、&x[i]);
}
//等待两个线程完成执行。。。
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
这是因为
x
数组将在调用
pthread\u join()
之后生存。也不需要强制转换指针,
int*
在C中自动转换为
void*

另外,关于线程启动顺序的假设是错误的,没有这样的保证。

两件事

1) 此处,x变量范围仅限于if块。所以在你的线程函数中,当你访问指针时,它的作用域消失了,所以你在线程函数中访问非法内存,这是错误的,它将创建未定义的行为

回应你的一个评论


那么有没有什么方法可以代替变量直接发送一个常量,例如pthread_create(&tid[I],&arg,function,6)

POSIX线程是一个C API。C不提供语言工具,如 复制构造函数,因此不可能通过 价值观

您需要始终只通过指针传递内容。

2) 线程执行的优先级完全取决于操作系统和调度,您不能假定这些线程的顺序


您仍然希望线程之间进行一些同步,然后使用互斥体、条件变量等。

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

很可能您正在多核系统上进行测试。然后,它们甚至可能同时并行运行,但出于某种原因,其中一个可能更快(可能第二个的数据在缓存中,而第一个必须从内存中获取数据?)

长话短说:没有任何保证

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

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

这个假设是不正确的,它依赖于由操作系统控制的线程调度

如果希望看到正确的输出,请在
main()
函数作用域中声明两个变量(在
之前用于
循环)

同时也要改变

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

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

x
在创建线程时就超出范围,因此您的代码显示UB。请在线程中尝试这样做:
printf(“%p\n”,x),我猜,您会看到,两个线程的指针是相同的,因为您的
intx=0/6在本地范围内,因此它们可能最终分配到相同的地址。所以您使用的是线程,但您希望它们之间有特定的执行顺序?你认为启动一个线程和调用一个方法之间的区别是什么?@Roman Hocke:是的,我明白你的意思,谢谢:)可能的重复,等等。那么有没有什么方法可以直接发送一个常量而不是变量,例如pthread_create(&tid[I],&arg,function,6)??@MuzahirHussain:在启动线程之前,您可以
malloc
变量的缓冲区,将指向该缓冲区的指针传递给线程,并在使用完缓冲区后,让线程本身
释放该缓冲区。函数指针数组的声明不正确。函数返回一个
void*
not
void
,因此声明需要类似于:
void*(*func[])(void*)={function,functionB}@user3629249谢谢,修复!
int x = 0;  
int y = 6;  
pthread_create(&tid[i], &arg, functionA, (void*)&x);
 pthread_create(&tid[i], &arg, functionB, (void*)&y);