时间:2010-07-25 16:38:30

标签: c pthreads

9 个答案:

答案 0 :(得分:18)

答案 1 :(得分:4)

答案 2 :(得分:3)

答案 3 :(得分:1)

答案 4 :(得分:1)

如果pthread_join(reader,NULL);Context被声明为具有静态存储持续时间,则根本不需要调用buffer(正如Steve Jessop,caf和David Schwartz已经指出的那样)。

声明Contextbuffer静态也需要将Context *context分别更改为Context *contextrContext *contextw

此外,以下称为pthread_exit.c的重写将sem_init()替换为sem_open()并使用nanosleep()(根据Jonathan Leffler的建议)。

pthread_exit在Mac OS X 10.6.8上测试过,未输出任何ASCII NUL字符。

/*

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 <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <semaphore.h>

#include <time.h>

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;
}

答案 5 :(得分:0)

答案 6 :(得分:0)

答案 7 :(得分:0)

答案 8 :(得分:0)

当您向线程传递指向变量的指针时,您需要确保该变量的生命周期至少与线程尝试访问该变量一样长。您将线程指针传递给buffercontext,它们分配在main内的堆栈上。一旦main退出,这些变量就不复存在了。因此,在确认这些线程不再需要访问这些指针之前,您无法退出main

95%的情况下,解决此问题的方法是遵循以下简单模式:

  

1)分配一个对象来保存参数。

     

2)用参数填充对象。

     

3)将指向对象的指针传递给新线程。

     

4)允许新线程解除分配对象。

可悲的是,这对两个或多个线程共享的对象不起作用。在这种情况下,您可以在参数对象中放置一个使用计数和一个互斥锁。每个线程都可以在互斥锁保护完成后减少使用次数。将使用次数降为零的线程释放对象。

您需要为buffercontext执行此操作。将使用次数设置为2,然后将指向此对象的指针传递给两个线程。