简体   繁体   English

使用pthread_join(线程,NULL)时出现混淆

[英]confusion in using of pthread_join ( thread, NULL)

When we create a thread with pthread_create , should we place the pthread_join immediate? 当我们使用pthread_create创建线程时,是否应该将pthread_join立即放置?

For example I have the following two codes, but I do not know why it does not work. 例如,我有以下两个代码,但是我不知道为什么它不起作用。

For the 1st version, the output is not deterministic. 对于第一个版本,输出不确定。

#include<iostream>
#include<pthread.h>
#include<cstring>
#include<cstdlib>
#define ROW 3
#define COL 3
using namespace std;
typedef struct {
int row;
int col;
} para;
void print(double * para)
{
    for(int i=0;i<3;i++)
   {
           for(int j=0;j<3;j++)
           {
                    cout<<*(para+3*i+j)<<"\t";
            }
            cout<<endl;
        }

}
double mat[9]={1,2,3,4,5,6,7,8,9};
double * result=(double *) malloc(9*sizeof(double));
void * mul(void * arg)
{
        para * temp=(para *) arg;
        int row=temp->row;
        int col=temp->col;
        double sum=0;
        for(int i=0;i<3;i++)
        {
                double a=*(mat+row*3+i);
                double b=*(mat+i+3*col);
                sum+=a*b;
        }
        *(result+row*3+col)=sum;
int main()
{
        pthread_t thread[9];
        for(int i=0;i<9;i++)
        {
                   para M;
                M.row=i/3;
                M.col=i%3;
                pthread_create(&thread[i],NULL,mul,&M);

        }
        for(int i=0;i<9;i++)
        {
                 pthread_join(thread[i],NULL);            
        }

        print(result);
}

With the 2nd version, the output is correct. 对于第二版,输出正确。

#include<iostream>
#include<pthread.h>
#include<cstring>
#include<cstdlib>
#define ROW 3
#define COL 3
using namespace std;
typedef struct {
int row;
int col;
} para;
void print(double * para)
{
    for(int i=0;i<3;i++)
   {
           for(int j=0;j<3;j++)
           {
                    cout<<*(para+3*i+j)<<"\t";
            }
            cout<<endl;
        }

}
double mat[9]={1,2,3,4,5,6,7,8,9};
double * result=(double *) malloc(9*sizeof(double));
void * mul(void * arg)
{
        para * temp=(para *) arg;
        int row=temp->row;
        int col=temp->col;
        double sum=0;
        for(int i=0;i<3;i++)
        {
                double a=*(mat+row*3+i);
                double b=*(mat+i+3*col);
                sum+=a*b;
        }
        *(result+row*3+col)=sum;
int main()
{
        pthread_t thread[9];
        for(int i=0;i<9;i++)
        {
                   para M;
                M.row=i/3;
                M.col=i%3;
                pthread_create(&thread[i],NULL,mul,&M);
                pthread_join(thread[i],NULL); 
        }   
        print(result);
}

What is the difference between these two usages? 这两种用法有什么区别? And why the first code has something wrong? 为什么第一个代码有问题?

The first version starts nine threads. 第一个版本启动九个线程。
Then once all threads have been created it waits for them all to finish before exiting. 然后,一旦创建了所有线程,它将等待所有线程完成后再退出。
Thus you get nine threads running in parallel. 因此,您获得了九个并行运行的线程。

The second version starts nine threads. 第二个版本启动九个线程。
But after each thread is started it waits for the thread to exit before continuing. 但是,在启动每个线程之后,它将等待线程退出,然后再继续。
Thus you get nine threads running serially. 因此,您获得了九个串行运行的线程。

Unfortunately the first version is also broken. 不幸的是,第一个版本也被破坏了。
The data object passed to the thread (as the 4th parameter ( &M )) is an automatic variable that goes out of scope potentially before the thread completes. 传递给线程的数据对象(作为第四个参数( &M ))是一个自动变量,可能在线程完成之前超出范围。

Fix like this: 像这样修复:

    pthread_t thread[9];
    para      M[9];
    for(int i=0;i<9;i++)
    {
            M[i].row = i/3;
            M[i].col = i%3;
            pthread_create(&thread[i],NULL,mul,&M[i]);

    }

All your threads share the same memory region as their parameter because you repeatedly pass the pointer to the same stack-allocated variable M . 您的所有线程都与其参数共享相同的内存区域,因为您反复将指针传递给相同的堆栈分配变量M You change M in the main loop while worker threads are running, leading to non-deterministic results. 当工作线程正在运行时,您可以在主循环中更改M ,从而导致不确定的结果。 In the 2nd version you've essentially turned your code into sequential, as pthread_join waits for every thread to terminate before you start next, that's why it works correctly. 在第二版中,您实际上已将代码转换为顺序代码,因为pthread_join在下一个启动之前等待每个线程终止,这就是为什么它可以正常工作的原因。

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

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