C++ 为什么主功能可以';t将正确的参数传递给pthread_create函数

C++ 为什么主功能可以';t将正确的参数传递给pthread_create函数,c++,C++,我试图通过限制哲学家的数量来解决哲学家的问题,他们的饮食习惯是4。在main函数中,我这样编写代码来创建线程 for (i = 0; i < N; i++) { pthread_create(&tidp[i], NULL, creatPhilosopher, (void *)&i); } 而我尝试了另一种方式 for (i = 0; i < N; i++) { int* temp = (int*)malloc(sizeof(

我试图通过限制哲学家的数量来解决哲学家的问题,他们的饮食习惯是4。在main函数中,我这样编写代码来创建线程

for (i = 0; i < N; i++) {
        pthread_create(&tidp[i], NULL, creatPhilosopher, (void *)&i);
    }
而我尝试了另一种方式

 for (i = 0; i < N; i++) {
        int* temp = (int*)malloc(sizeof(int));
        *temp = i;
        pthread_create(&tidp[i], NULL, creatPhilosopher, (void *)temp);
    }

那么,这两种方法有什么区别呢?

在第一种情况下,只有一个内存位置被传递给所有不同的线程:变量
i
的地址。因此,所有线程将从同一位置读取它们的编号。他们从中读取的内容取决于他们何时读取该值。看起来都是0有点奇怪,但无论如何,这不是你想要的


在第二种情况下,为每个线程指定不同的内存位置。因此,每个线程从不同的位置读取数据,从而读取不同的数字。

在第一种情况下,只有一个内存位置被传递给所有不同的线程:变量
i
的地址。因此,所有线程将从同一位置读取它们的编号。他们从中读取的内容取决于他们何时读取该值。看起来都是0有点奇怪,但无论如何,这不是你想要的


在第二种情况下,为每个线程指定不同的内存位置。因此,每个线程从不同的位置读取数据,从而读取不同的数字。

在第一个示例中,为每个线程传递指向相同变量的指针/引用/句柄。一个变量包含一个值。您也没有同步对该变量的访问(更不用说它可能在每个线程尝试从中读取之前被销毁),所以实际上所有的赌注都被取消了

在第二个示例中,每个线程都会获得一个具有正确值的
i
副本,因为变量是独立的对象,所以也具有线程安全性


您应该始终考虑对象生存期、所有权和访问模式。

在第一个示例中,您为每个线程向同一个变量传递指针/引用/句柄。一个变量包含一个值。您也没有同步对该变量的访问(更不用说它可能在每个线程尝试从中读取之前被销毁),所以实际上所有的赌注都被取消了

在第二个示例中,每个线程都会获得一个具有正确值的
i
副本,因为变量是独立的对象,所以也具有线程安全性


您应该始终考虑对象生命周期、所有权和访问模式。

区别在于未定义的行为

for (i = 0; i < N; i++) {
     pthread_create(&tidp[i], NULL, creatPhilosopher, (void *)&i);
}
(i=0;i{ pthread_create(&tidp[i],NULL,creatSpherector,(void*)&i); }

既不使用C++线程标准,也不使用POSIX,它使用的线程API,无论是什么,都可以保证,<代码> CalpEngule<代码>将开始执行并读取指针在“<代码> > <代码>循环迭代结束之前传递给它的指针的值,以便新线程读取当前代码的值<代码> i>代码>。无法保证在主执行线程中返回

pthread\u create
之前,
createSpropher
确实开始执行。可能会,也可能不会。这取决于月亮的相位和潮汐

当执行线程开始执行时,整个
for
循环可能已经完成,只是一个遥远的内存。它多次调用了
pthread\u create
(但它们的执行线程尚未开始执行),事实上,
i
变量现在已被销毁,不再存在(无论它在何处声明),它的内存现在被其他一些随机选择的值或垃圾所占用,因此,当新的执行线程读取作为参数接收的指针时,它指向了垃圾


在另一种情况下,您在动态范围中分配一个
int
值,该值在执行线程实际开始执行时仍然存在,因此它们读取该值。没有任何内容可以释放它们,因此指针仍然是值。你泄露了内存,但那是另一回事。

区别在于未定义的行为

for (i = 0; i < N; i++) {
     pthread_create(&tidp[i], NULL, creatPhilosopher, (void *)&i);
}
(i=0;i{ pthread_create(&tidp[i],NULL,creatSpherector,(void*)&i); }

既不使用C++线程标准,也不使用POSIX,它使用的线程API,无论是什么,都可以保证,<代码> CalpEngule<代码>将开始执行并读取指针在“<代码> > <代码>循环迭代结束之前传递给它的指针的值,以便新线程读取当前代码的值<代码> i>代码>。无法保证在主执行线程中返回

pthread\u create
之前,
createSpropher
确实开始执行。可能会,也可能不会。这取决于月亮的相位和潮汐

当执行线程开始执行时,整个
for
循环可能已经完成,只是一个遥远的内存。它多次调用了
pthread\u create
(但它们的执行线程尚未开始执行),事实上,
i
变量现在已被销毁,不再存在(无论它在何处声明),它的内存现在被其他一些随机选择的值或垃圾所占用,因此,当新的执行线程读取作为参数接收的指针时,它指向了垃圾


在另一种情况下,您在动态范围中分配一个
int
值,该值在执行线程实际开始执行时仍然存在,因此它们读取该值。没有任何内容可以释放它们,因此指针仍然是值。

如果你使用C++,你应该使用<代码> STD::线程< /COD>和<代码>新< /C> >代替<代码> PTGReDeLead < /COD>和<代码> MalOC ,在这种情况下,你不需要新的/MALOC,因为你可以通过值传递给<代码> STD::
for (i = 0; i < N; i++) {
     pthread_create(&tidp[i], NULL, creatPhilosopher, (void *)&i);
}