首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >试图理解POSIX线程

试图理解POSIX线程
EN

Stack Overflow用户
提问于 2015-03-20 23:00:27
回答 3查看 60关注 0票数 1

我试图掌握POSIX线程的使用情况,并创建了一个简单的程序,只需将全局变量增加10。有时,它会一直运行到很好的地方,而其他程序则会将故障随机地插入。虽然这种类型的问题似乎是线程的常规问题,但我无法理解为什么在这样一个简单的例子中会出现这种情况。我目前的想法是,由于没有加入线程,父线程可能会在结束之前结束,但是如果我试图加入,我会在第一个线程上设置错误.Join语句保留在其中,但是注释掉了。联接是否以正确的语法使用?预先形成的连接不是导致seg故障吗?

代码语言:javascript
运行
复制
#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");
}

产出:

代码语言:javascript
运行
复制
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

下一次跑:

代码语言:javascript
运行
复制
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)

一如既往,任何帮助都是非常感谢的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-03-20 23:18:51

你面临的主要问题是:

代码语言:javascript
运行
复制
    if( pthread_create(&threads[i], NULL, (void *)philofunct(),(void *) &i) != 0)

仔细观察,您正在调用philofunct(),而不是将函数指针传递给它。更糟糕的是,您传递的是philofunct()的返回值,它是一些整数,如15,作为指向pthread_create()的函数指针。当然,当线程试图从一个地址(如15 )执行代码时,它将进行分段。

正确定义philofunct()后,如下所示:

代码语言:javascript
运行
复制
void *philofunct(void *arg)

然后,无需强制转换就可以调用pthread_create()

代码语言:javascript
运行
复制
    if( pthread_create(&threads[i], NULL, philofunct,(void *) &i) != 0)

此外,如果您想要加入您的线程,您应该加入您的线程后,他们都运行。如果您加入了创建循环中的线程,那么在创建下一个线程之前,您将等待每个线程完成。所以你会这样写:

代码语言:javascript
运行
复制
for (i=0;i<NUMPHILO; i++) {
    pthread_create(&threads[i], ...);
    // Other stuff...
}
for (i=0;i<NUMPHILO; i++)
    pthread_join(threads[i], NULL);
票数 4
EN

Stack Overflow用户

发布于 2015-03-20 23:08:50

在考虑您想要的内容之前,我看到了代码中的几个问题:

  • 您不能像这样转换函数指针并期望得到有意义的结果。相反,给函数正确的签名,并将参数/返回值转换到函数的边缘。但是您通常不需要使用返回值。
  • 您正在访问被互斥体锁定的部分之外的变量x
  • 您正在销毁互斥对象,而不需要等待使用它的所有线程退出。您需要第二个循环才能将它们全部pthread_join。或者,您可以pthread_exit主线程,而不是让main终止(永远不要破坏互斥,这不是泄漏,因为只有一个互斥线程,并且它的生命周期随着程序的生命周期而结束),但是杀死主线程有时会产生有趣的内核“but”。
票数 4
EN

Stack Overflow用户

发布于 2015-03-20 23:18:34

主线程在子线程完成互斥之前正在销毁互斥体。pthread_join可以解决这个问题,但是在创建了所有线程之后,pthread_join需要处于一个单独的循环中。

代码语言:javascript
运行
复制
for(int i = 0; i < NUMPHILO; i++) 
   pthread_join(threads[i],NULL); 

philofunct的函数签名是错误的。一般来说,如果你需要演员,你做错了什么。(是的,在某些情况下,铸造是必要的和有用的。这不是其中之一。)正确的签名是

代码语言:javascript
运行
复制
void *philofunct( void *arg );

pthread_create的正确调用是

代码语言:javascript
运行
复制
if( pthread_create(&threads[i], NULL, philofunct, NULL) != 0)

请注意,传递i的地址并不能满足您的要求,但这是一个单独的问题,您还没有达到这一点。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29177083

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档