【问题标题】:Creating threads with recursion with c使用 c 递归创建线程
【发布时间】:2018-12-18 04:17:40
【问题描述】:

我的任务是实现一个 C 程序生成带有 id 的线程树,以便主线程将其 id(不是线程 id,而是由信号量管理的全局变量)推送到数据结构中,然后再创建 2 个线程然后终止不向线程传递任何参数。

它必须由共享变量管理,所以每个线程推送它的 id 然后再创建 2 个线程并在 (2^n) 留下创建的线程后终止进程停止,每个叶子线程应该推送它的 id 并打印它的线程树然后终止。

我选择一棵二叉树,我正在生成线程,但不知何故,程序在到达第一片叶子后停止,它打印它的叶子树然后退出,我不明白为什么:你能解释一下我在这里做错了什么它为什么存在? 这是我的代码

#include <stdio.h>
#include <stdlib.h>
#include <math.h>    
#include <pthread.h>
#include <semaphore.h>


typedef struct link{
    int id;
    struct link *parent;
    struct link *left;
    struct link *right;
}b_tree;


int id = 1;
int max_id = 0;
int n;
b_tree *t_tree = NULL;
sem_t sem, semp;

void *create_tree();
b_tree *new_node();
b_tree *search_tree(b_tree *, int);
void print_path(b_tree *);
void free_tree(b_tree *);

int main(int argc, char *argv[])
{

    int r, i;
    pthread_t tid;
    b_tree *node;
    if (argc < 2) {
        fprintf(stderr, "Missing argument\n");
        exit(1);
    }
    n = atoi(argv[1]);
    sem_init(&sem, 0, 1);
    sem_init(&semp, 0, 1);
    for(i = 0; i <= n; i++){
        max_id+=(int)pow(2,i);
    }
    node = new_node();
    node->id = id;
    t_tree = node;
    id++;
    for (i = 0; i < 2; i++) {
        r = pthread_create(&tid, NULL, create_tree(), NULL);
        if(r){
            fprintf(stderr, "Thread creation failed\n");
            exit(1);
        }
    }
    pthread_exit(NULL);
}

b_tree *new_node(){
    b_tree *node;
    node = (b_tree *)malloc(sizeof(b_tree));
    if(node == NULL){
        fprintf(stderr, "Memory allocation error\n");
        exit(1);
    }
    node->left = NULL;
    node->right = NULL;
    node->id = -1;
    node->parent = NULL;
    return node;
}

b_tree *search_tree(b_tree *root, int key){
    b_tree *l = NULL, *r = NULL;
    if(root == NULL){
        return NULL;
    }
    if(root->id == key){
        return root;
    }
    l = search_tree(root->left, key);
    r = search_tree(root->right, key);
    if(l != NULL && l->id == key){
        return l;
    }else if(r != NULL && r->id == key){
        return r;
    }
    return NULL;
}

void *create_tree(){
    b_tree *node;
    int pid, i, r;
    pthread_t tid;
    node = new_node();
    //Enter the critical section
    sem_wait(&sem);
    if(id <= max_id){
        node->id = id;
        id++;
    }
    sem_post(&sem);
    //Exit from the critical section
    pid = (int)node->id/2; //compute the parent id
    //get parent and connect the tree
    node->parent = search_tree(t_tree, pid);
    if(node->parent != NULL){
        if(node->parent->left == NULL){
            node->parent->left = node;
        }else{
            node->parent->right = node;
        }
    }else{
        fprintf(stderr, "No parent found\n");
        exit(1);
    }
    //Check if it is a leaf
    if(node->id >= pow(2,n) && node->id <= max_id){
        sem_wait(&semp);
        print_path(node);
        sem_post(&semp);
        if(node->id == max_id){ //if it is the last leaf
            free_tree(t_tree);
        }
    }else{//not a leaf
        for(i = 0; i < 2; i++){//create 2 more threds and terminate
            r = pthread_create(&tid, NULL, create_tree(), NULL);
            if(r > 0){
                fprintf(stderr, "Thread creation failed\n");
                exit(1);
            }
        }
        printf("This node was not a leaf and it created 2 more threads\n");
    }
    pthread_exit(NULL);
}

void print_path(b_tree *leaf){
    if(leaf != NULL) printf("Thread tree: ");
    while(leaf != NULL){
        printf("%d ", leaf->id);
        leaf = leaf->parent;
    }
    printf("\n");
    return;
}

void free_tree(b_tree *root){
    if(root == NULL){
        return;
    }
    free_tree(root->left);
    free_tree(root->right);
    free(root);
    return;
}

【问题讨论】:

  • 你做错了什么,很难理解?可能使用递归。
  • @barny 我想要做的是让每个线程通过信号量使用互斥访问全局变量 id 获取其当前值然后递增它并在树中创建一个节点搜索其父节点和连接它然后检查它是否是叶线程,如果是,它使用 print_path 方法打印路径,否则它创建 2 个新线程并终止
  • 我想象你的任务的结论是递归非常非常非常非常难以成功设计、理解、调试和维护。祝你好运!

标签: c multithreading


【解决方案1】:

如果你想让你的程序等待线程完成,你必须调用pthread_join(pthread_t) 和你要等待的线程的id(我猜都是)。然后你应该在你的线程函数中调用我认为相同的函数来等待新创建的线程。

这一切对我来说似乎很危险,所以要小心。

还要注意一件事:线程和你的主程序正在做同样的事情。您是否考虑过使用fork() 来创建进程而不是线程?

【讨论】:

  • 感谢您的回复,该任务要求线程在将其 id 添加到树并创建恰好 2 个子线程后终止,并且不应该等待它们终止,这就是我不这样做的原因使用pthread_join(),主要使用pthread_exit(),所以它不会杀死其他线程,关于使用fork(),要求是使用线程来完成。
  • 我想说的是:在main 中创建前两个线程之后,您正在调用pthread_exit(),这使得主线程退出因此终止程序:这将终止整个程序是否其他线程已完成。您看不到正在生成的其他线程的原因是您的程序在有时间创建它们之前就退出了。您可以尝试在退出前添加延迟,并检查是否会创建其他线程。
  • 我照你说的做了,但结果还是一样,无论如何bthread_exit()不应该只终止主线程而不杀死其他线程让它们运行。
  • inorder_visitcreate_tree 的库是什么?我会试试代码
  • 谢谢,这是帮我打印树的辅助功能,我忘了删除它,我现在将编辑代码
【解决方案2】:

这里的问题很少。

  • t_treemain 中初始化一次,之后就不再修改,并且可能多次为freed(请参阅下一个项目符号)。

  • create_tree() 仅在 id &lt;= max_id 时分配 node-&gt;id。到考试的时候

        if(node->id >= pow(2,n) && node->id <= max_id)
    

    已执行,node-&gt;id 可能未初始化。

  • inorder_visit()(未在帖子中定义)也可能导致未定义的行为。

【讨论】:

  • 谢谢,我会修改它们,主要错误是我使用函数 pthread_create 的返回值而不是指向函数的指针。
【解决方案3】:

主要问题出在pthread_create() 中,我使用返回的值但函数作为参数,而不是使用指向函数本身的指针。 pthread_create(&amp;tid, NULL, create_tree, NULL);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多