pthreads in C - pthread_exit

前端 未结 9 1250
北荒
北荒 2021-02-05 14:03

For some reason I thought that calling pthread_exit(NULL) at the end of a main function would guarantee that all running threads (at least created in the main funct

9条回答
  •  终归单人心
    2021-02-05 14:16

    There is no need for calling pthread_join(reader,NULL); at all if Context and buffer are declared with static storage duration (as already pointed out by Steve Jessop, caf and David Schwartz).

    Declaring Context and buffer static also makes it necessary to change Context *context to Context *contextr or Context *contextw respectively.

    In addition, the following rewrite called pthread_exit.c replaces sem_init() with sem_open() and uses nanosleep() (as suggested by Jonathan Leffler).

    pthread_exit was tested on Mac OS X 10.6.8 and did not output any ASCII NUL characters.

    /*
    
    cat pthread_exit.c  (sample code to test pthread_exit() in main())
    
    source: 
    "pthreads in C - pthread_exit",
    http://stackoverflow.com/questions/3330048/pthreads-in-c-pthread-exit
    
    compiled on Mac OS X 10.6.8 with:
    gcc -ansi -pedantic -std=gnu99 -Os -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-qual  -Wstrict-prototypes \
        -Wmissing-prototypes -Wformat=2 -l pthread -o pthread_exit pthread_exit.c
    
    test with: 
    time -p bash -c './pthread_exit | tee >(od -c 1>&2) | wc -c'
    
    */
    
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include 
    
    void *Reader(void* arg);
    void *Writer(void* arg);
    
    // #define NUM_CHAR 1024
    #define NUM_CHAR 100
    #define BUFFER_SIZE 8
    
    typedef struct {
        pthread_mutex_t mutex; 
        sem_t *full;
        sem_t *empty;
        const char *semname1;
        const char *semname2;
        char* buffer;
    } Context;
    
    
    static char buffer[BUFFER_SIZE];
    static Context context;
    
    void *Reader(void* arg) {
        Context *contextr = (Context*) arg;
        for (int i = 0; i < NUM_CHAR; ++i) {
            sem_wait(contextr->full);
            pthread_mutex_lock(&(contextr->mutex));
            char c = contextr->buffer[i % BUFFER_SIZE];
            pthread_mutex_unlock(&(contextr->mutex));
            sem_post(contextr->empty);
            printf("%c", c);
        }
        printf("\n");
        return NULL;
    }
    
    void *Writer(void* arg) {
        Context *contextw = (Context*) arg;
        for (int i = 0; i < NUM_CHAR; ++i) {
            sem_wait(contextw->empty);
            pthread_mutex_lock(&(contextw->mutex));
            contextw->buffer[i % BUFFER_SIZE] = 'a' + (rand() % 26);
            float ranFloat = (float) rand() / RAND_MAX;
            //if (ranFloat < 0.5) sleep(0.2);
            if (ranFloat < 0.5)
               nanosleep((struct timespec[]){{0, 200000000L}}, NULL);
            pthread_mutex_unlock(&(contextw->mutex));
            sem_post(contextw->full);
        }
        return NULL;
    }
    
    int main(void) {
        pthread_t reader, writer;
        srand(time(NULL));
        int status = 0;
        status = pthread_mutex_init(&context.mutex, NULL);
        context.semname1 = "Semaphore1";
        context.semname2 = "Semaphore2";
    
        context.full = sem_open(context.semname1, O_CREAT, 0777, 0);
        if (context.full == SEM_FAILED)
        {
            fprintf(stderr, "%s\n", "ERROR creating semaphore semname1");
            exit(EXIT_FAILURE);
        }
    
        context.empty = sem_open(context.semname2, O_CREAT, 0777, BUFFER_SIZE);
        if (context.empty == SEM_FAILED)
        {
            fprintf(stderr, "%s\n", "ERROR creating semaphore semname2");
            exit(EXIT_FAILURE);
        }
    
        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
    
        sem_unlink(context.semname1);
        sem_unlink(context.semname2);
    
        pthread_exit(NULL);
    
        return 0;
    }
    

提交回复
热议问题