答案 0 :(得分:18)
答案 1 :(得分:4)
答案 2 :(得分:3)
答案 3 :(得分:1)
答案 4 :(得分:1)
如果pthread_join(reader,NULL);
和Context
被声明为具有静态存储持续时间,则根本不需要调用buffer
(正如Steve Jessop,caf和David Schwartz已经指出的那样)。
声明Context
和buffer
静态也需要将Context *context
分别更改为Context *contextr
或Context *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)
当您向线程传递指向变量的指针时,您需要确保该变量的生命周期至少与线程尝试访问该变量一样长。您将线程指针传递给buffer
和context
,它们分配在main
内的堆栈上。一旦main
退出,这些变量就不复存在了。因此,在确认这些线程不再需要访问这些指针之前,您无法退出main
。
95%的情况下,解决此问题的方法是遵循以下简单模式:
1)分配一个对象来保存参数。
2)用参数填充对象。
3)将指向对象的指针传递给新线程。
4)允许新线程解除分配对象。
可悲的是,这对两个或多个线程共享的对象不起作用。在这种情况下,您可以在参数对象中放置一个使用计数和一个互斥锁。每个线程都可以在互斥锁保护完成后减少使用次数。将使用次数降为零的线程释放对象。
您需要为buffer
和context
执行此操作。将使用次数设置为2
,然后将指向此对象的指针传递给两个线程。