试图了解 POSIX 个话题
Trying to understand POSIX Threads
我试图掌握 POSIX 线程的使用,并创建了一个简单的程序,该程序只需将全局变量递增 10。有时它会一直运行良好,其他情况下会出现段错误在 运行dom 点。虽然这种类型的问题似乎是线程的常见问题,但我无法理解为什么在这样一个简单的示例中会发生这种情况。我目前的想法是,由于未加入线程,父级可能在此之前结束,但如果我尝试加入,我会在第一个线程上出现段错误...... Join 语句被保留但被注释掉了。 Join 是否以正确的语法使用?没有执行连接会导致段错误吗?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#define NUMPHILO 5
thread_t threads[NUMPHILO]; //array of threads
pthread_mutex_t mutex; // initialize mutex
int x = 5; //for test
int y = 10;
int philofunct(){
pthread_mutex_lock (&mutex);
x = x+y;
pthread_mutex_unlock (&mutex);
printf("Philo fucntion x = %d\n",x);
return x;
}
int main(){
pthread_mutex_init(&mutex, NULL);
for(int i = 0; i < NUMPHILO; i++){
printf("creating thread[%i]\n",i);
if( pthread_create(&threads[i], NULL, (void *)philofunct(),(void *) &i) != 0)
fprintf(stderr, "%s", strerror(errno));
// pthread_join(threads[i],NULL);
// printf("Threads Joined\n");
}
pthread_mutex_destroy(&mutex);
printf("Threads created\n");
}
输出:
creating thread[0]
Philo fucntion x = 15
creating thread[1]
Philo fucntion x = 25
creating thread[2]
Philo fucntion x = 35
creating thread[3]
Philo fucntion x = 45
creating thread[4]
Philo fucntion x = 55
Threads created
下次运行:
creating thread[0]
Philo fucntion x = 15
creating thread[1]
Philo fucntion x = 25
creating thread[2]
Philo fucntion x = 35
Segmentation fault (core dumped)
一如既往,非常感谢您的帮助。
在考虑你想要什么之前,我发现你的代码有几个问题:
- 您不能像那样转换函数指针并期望得到有意义的结果。相反,为函数提供正确的签名并在函数的边缘投射 argument/return 值。但是您实际上通常不需要使用 return 值。
- 您正在访问被互斥锁锁定的部分之外的变量
x
。
- 您正在销毁互斥锁,而没有等待所有使用它的线程退出。你需要第二个循环来
pthread_join
它们。或者,您可以 pthread_exit
主线程而不是让 main
终止(并且永远不会破坏互斥量,这不是泄漏,因为只有其中一个并且它的生命周期以程序的生命周期结束) , 但杀死主线程有时会使有趣的内核 "bugs" 发生。
主线程在子线程完成互斥量之前销毁它。 pthread_join
将解决问题,但 pthread_join
需要在创建所有线程后单独循环。
for(int i = 0; i < NUMPHILO; i++)
pthread_join(threads[i],NULL);
philofunct
的函数签名错误。一般来说,如果你需要演员表,那你就做错了。 (是的,在某些情况下强制转换是必要且有用的。这不是其中之一。)正确的签名是
void *philofunct( void *arg );
pthread_create
的正确调用是
if( pthread_create(&threads[i], NULL, philofunct, NULL) != 0)
请注意,传递 i
的地址不会满足您的要求,但这是一个单独的问题,您还没有做到这一点。
你遇到的主要问题是:
if( pthread_create(&threads[i], NULL, (void *)philofunct(),(void *) &i) != 0)
仔细看,你是在调用philofunct()
而不是传递函数指针给它。更糟糕的是,您正在传递 philofunct()
的 return 值,它是一些整数,例如 15
,作为指向 pthread_create()
的函数指针。自然地,当线程尝试从诸如 15
.
这样的地址执行代码时,它会 segv
一旦你像这样正确定义了 philofunct()
:
void *philofunct(void *arg)
然后您可以调用 pthread_create()
而无需转换:
if( pthread_create(&threads[i], NULL, philofunct,(void *) &i) != 0)
另外,如果你想加入你的话题,你应该在他们都运行之后加入你的话题。如果您在创建循环中加入线程,您将在创建下一个线程之前等待每个线程完成。所以你会这样写:
for (i=0;i<NUMPHILO; i++) {
pthread_create(&threads[i], ...);
// Other stuff...
}
for (i=0;i<NUMPHILO; i++)
pthread_join(threads[i], NULL);
我试图掌握 POSIX 线程的使用,并创建了一个简单的程序,该程序只需将全局变量递增 10。有时它会一直运行良好,其他情况下会出现段错误在 运行dom 点。虽然这种类型的问题似乎是线程的常见问题,但我无法理解为什么在这样一个简单的示例中会发生这种情况。我目前的想法是,由于未加入线程,父级可能在此之前结束,但如果我尝试加入,我会在第一个线程上出现段错误...... Join 语句被保留但被注释掉了。 Join 是否以正确的语法使用?没有执行连接会导致段错误吗?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#define NUMPHILO 5
thread_t threads[NUMPHILO]; //array of threads
pthread_mutex_t mutex; // initialize mutex
int x = 5; //for test
int y = 10;
int philofunct(){
pthread_mutex_lock (&mutex);
x = x+y;
pthread_mutex_unlock (&mutex);
printf("Philo fucntion x = %d\n",x);
return x;
}
int main(){
pthread_mutex_init(&mutex, NULL);
for(int i = 0; i < NUMPHILO; i++){
printf("creating thread[%i]\n",i);
if( pthread_create(&threads[i], NULL, (void *)philofunct(),(void *) &i) != 0)
fprintf(stderr, "%s", strerror(errno));
// pthread_join(threads[i],NULL);
// printf("Threads Joined\n");
}
pthread_mutex_destroy(&mutex);
printf("Threads created\n");
}
输出:
creating thread[0]
Philo fucntion x = 15
creating thread[1]
Philo fucntion x = 25
creating thread[2]
Philo fucntion x = 35
creating thread[3]
Philo fucntion x = 45
creating thread[4]
Philo fucntion x = 55
Threads created
下次运行:
creating thread[0]
Philo fucntion x = 15
creating thread[1]
Philo fucntion x = 25
creating thread[2]
Philo fucntion x = 35
Segmentation fault (core dumped)
一如既往,非常感谢您的帮助。
在考虑你想要什么之前,我发现你的代码有几个问题:
- 您不能像那样转换函数指针并期望得到有意义的结果。相反,为函数提供正确的签名并在函数的边缘投射 argument/return 值。但是您实际上通常不需要使用 return 值。
- 您正在访问被互斥锁锁定的部分之外的变量
x
。 - 您正在销毁互斥锁,而没有等待所有使用它的线程退出。你需要第二个循环来
pthread_join
它们。或者,您可以pthread_exit
主线程而不是让main
终止(并且永远不会破坏互斥量,这不是泄漏,因为只有其中一个并且它的生命周期以程序的生命周期结束) , 但杀死主线程有时会使有趣的内核 "bugs" 发生。
主线程在子线程完成互斥量之前销毁它。 pthread_join
将解决问题,但 pthread_join
需要在创建所有线程后单独循环。
for(int i = 0; i < NUMPHILO; i++)
pthread_join(threads[i],NULL);
philofunct
的函数签名错误。一般来说,如果你需要演员表,那你就做错了。 (是的,在某些情况下强制转换是必要且有用的。这不是其中之一。)正确的签名是
void *philofunct( void *arg );
pthread_create
的正确调用是
if( pthread_create(&threads[i], NULL, philofunct, NULL) != 0)
请注意,传递 i
的地址不会满足您的要求,但这是一个单独的问题,您还没有做到这一点。
你遇到的主要问题是:
if( pthread_create(&threads[i], NULL, (void *)philofunct(),(void *) &i) != 0)
仔细看,你是在调用philofunct()
而不是传递函数指针给它。更糟糕的是,您正在传递 philofunct()
的 return 值,它是一些整数,例如 15
,作为指向 pthread_create()
的函数指针。自然地,当线程尝试从诸如 15
.
一旦你像这样正确定义了 philofunct()
:
void *philofunct(void *arg)
然后您可以调用 pthread_create()
而无需转换:
if( pthread_create(&threads[i], NULL, philofunct,(void *) &i) != 0)
另外,如果你想加入你的话题,你应该在他们都运行之后加入你的话题。如果您在创建循环中加入线程,您将在创建下一个线程之前等待每个线程完成。所以你会这样写:
for (i=0;i<NUMPHILO; i++) {
pthread_create(&threads[i], ...);
// Other stuff...
}
for (i=0;i<NUMPHILO; i++)
pthread_join(threads[i], NULL);