C语言中的pthreads | pthread_exit[英] pthreads in C - pthread_exit

本文是小编为大家收集整理的关于C语言中的pthreads | pthread_exit的处理方法,想解了C语言中的pthreads | pthread_exit的问题怎么解决?C语言中的pthreads | pthread_exit问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

出于某种原因,我认为在 main 函数结束时调用 pthread_exit(NULL) 可以保证所有正在运行的线程(至少在 main 函数中创建)将在 main 退出之前完成运行.但是,当我在下面运行此代码而不显式调用两个 pthread_join 函数(在 main 末尾)时,我得到了一个分段错误,这似乎是因为 main 函数在两个线程完成它们的工作之前已经退出,因此 char缓冲区不再可用.但是,当我在 main 末尾包含这两个 pthread_join 函数调用时,它会正常运行.为保证main在所有运行线程完成之前不会退出,是否需要为main中直接初始化的所有线程显式调用pthread_join?

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <semaphore.h>
#define NUM_CHAR 1024
#define BUFFER_SIZE 8

typedef struct {
    pthread_mutex_t mutex; 
    sem_t full;
    sem_t empty;
    char* buffer;
} Context;

void *Reader(void* arg) {
    Context* context = (Context*) arg;
    for (int i = 0; i < NUM_CHAR; ++i) {
        sem_wait(&context->full);
        pthread_mutex_lock(&(context->mutex));
        char c = context->buffer[i % BUFFER_SIZE];
        pthread_mutex_unlock(&(context->mutex));
        sem_post(&context->empty);

        printf("%c", c);
    }
    printf("\n");
    return NULL;
}

void *Writer(void* arg) {
    Context* context = (Context*) arg;
    for (int i = 0; i < NUM_CHAR; ++i) {
        sem_wait(&context->empty);
        pthread_mutex_lock(&(context->mutex));
        context->buffer[i % BUFFER_SIZE] = 'a' + (rand() % 26);
        float ranFloat = (float) rand() / RAND_MAX;
        if (ranFloat < 0.5) sleep(0.2);
        pthread_mutex_unlock(&(context->mutex));
        sem_post(&context->full);
    }
    return NULL;
}

int main() {
    char buffer[BUFFER_SIZE];
    pthread_t reader, writer;
    Context context;
    srand(time(NULL));
    int status = 0;
    status = pthread_mutex_init(&context.mutex, NULL);
    status = sem_init(&context.full,0,0);
    status = sem_init(&context.empty,0, BUFFER_SIZE);
    context.buffer = buffer;

    status = pthread_create(&reader, NULL, Reader, &context);
    status = pthread_create(&writer, NULL, Writer, &context);

    pthread_join(reader,NULL);   // This line seems to be necessary
    pthread_join(writer,NULL);   // This line seems to be necessary

    pthread_exit(NULL);
    return 0;
}

如果是这种情况,如果使用相同的线程标识符创建大量相同的线程(如下面的代码),我该如何处理?在这种情况下,如何确保所有线程在 main 退出之前都已完成?我真的必须保留一个 NUM_STUDENTS pthread_t 标识符的数组才能做到这一点吗?我想我可以通过让学生线程发出信号量然后让主函数等待该信号量来做到这一点,但真的没有更简单的方法吗?

int main()
{
    pthread_t thread;
    for (int i = 0; i < NUM_STUDENTS; i++)
        pthread_create(&thread,NULL,Student,NULL);  // Threads 
    // Make sure that all student threads have finished
    exit(0);
}

推荐答案

pthread_exit() 是一个线程调用的函数,用来终止自己的执行.对于您给出的情况,它不会从您的主程序线程中调用.

如您所见,pthread_join() 是等待来自 main() 的可连接线程完成的正确方法.

正如您所知道的,您需要维护从 pthread_create() 返回的值以传递给 pthread_join().

这意味着如果你打算使用 pthread_join(),你不能对你创建的所有线程使用相同的 pthread_t 变量.

相反,构建一个 pthread_t 数组,以便您拥有每个线程 ID 的副本.

本文地址:https://www.itbaoku.cn/post/358954.html