pthreads在C - pthread_exit中

Sig*_*ggi 14 c pthreads

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)

Ama*_*9MF 18

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

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

另外,正如您已经想到的那样,您需要保持返回的值pthread_create()以传递给pthread_join().

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

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

  • 你能否为你的陈述引用一个权限''永远不会从你的主程序线程调用'? (3认同)
  • @Jonathan:肯定不具有权威性.相反,它只是对pthreads新手的建议.也许我的语言遇到了错误的方式.我会调整它.谢谢你指出这一点. (2认同)

m1t*_*tk4 1

pthread_join()是等待其他线程完成的标准方法,我会坚持这样做。

或者,您可以创建一个线程计数器,并让所有子线程在开始时将其递增 1,然后在完成时将其递减 1(当然需要适当的锁定),然后等待main()该计数器达到 0。(pthread_cond_wait()将是我的选择)。