pthread生产者消费者问题
需求:
很简单,就是练习使用pthread实现生产者消费者模型
- 创建data_queue.c,用于缓存数据
- main线程,用于创建生产者和消费者线程
问题
- 第一次点击Start按钮,执行start(),程序正常执行
- 点击Stop按钮,执行stop(),程序中日志正常打印线程退出信息
- 再次点击start按钮,执行start(),生产者和消费者线程只打印一次生产数据和消费数据后,就卡在那里..,不知道是不是死锁??
代码如下:
代码被简化
- data_queue.c
#define MAX_QUEUE_SIZE 10
int student_queue_init(StudentQueue *queue) {
memset(queue, 0, sizeof(StudentQueue));
pthread_mutex_init(&queue->mutex, NULL);
pthread_cond_init(&queue->empty_queue, NULL);
pthread_cond_init(&queue->full_queue, NULL);
return 0;
}
int student_queue_put(StudentQueue *queue, Student student) {
pthread_mutex_lock(&queue->mutex);
while (queue->nb_students == (MAX_QUEUE_SIZE - 1)) {
LOGE("队列已满,等待消费");
pthread_cond_wait(&queue->full_queue, &queue->mutex);
}
StudentNode *node = (StudentNode *) malloc(sizeof(StudentNode));
node->student = student;
node->next = NULL;
if (!queue->rear) {
queue->front = node;
} else {
queue->rear->next = node;
}
queue->rear = node;
queue->nb_students++;
pthread_cond_signal(&queue->empty_queue);
pthread_mutex_unlock(&queue->mutex);
return 0;
}
int student_queue_get(StudentQueue *queue, Student *student) {
pthread_mutex_lock(&queue->mutex);
while (queue->nb_students <= 0) {
LOGE("队列中没有数据,等待生产");
pthread_cond_wait(&queue->empty_queue, &queue->mutex);
}
StudentNode *node = queue->front;
*student = node->student;
queue->front = node->next;
if (!queue->front) {
queue->rear = NULL;
}
queue->nb_students--;
pthread_cond_signal(&queue->full_queue);
pthread_mutex_unlock(&queue->mutex);
return 0;
}
int student_queue_destroy(StudentQueue *queue) {
pthread_mutex_lock(&queue->mutex);
StudentNode *temp;
for (temp = queue->front; temp; temp = temp->next) {
free(temp);
}
queue->front = NULL;
queue->rear = NULL;
pthread_mutex_unlock(&queue->mutex);
pthread_mutex_destroy(&queue->mutex);
pthread_cond_destroy(&queue->empty_queue);
pthread_cond_destroy(&queue->full_queue);
free(queue);
return 0;
}
- main.c
解释一下main.c
- Android中的JNI小栗子
- 点击Start按钮,执行Java_me_learn_JNIThread_start()函数
- 点击Stop按钮,执行Java_me_learn_JNIThread_stop()函数
static pthread_t producer;
static pthread_t consumer;
static int finished_producer = 0;
static int finished_consumer = 0;
void *producer_run(void *userdata) {
LOGE("生产者线程启动成功...\n");
StudentQueue *queue = (StudentQueue *) userdata;
int age = 0;
while (1) {
Student student;
student.age = age++;
sprintf(student.name, "name ... %d", student.age);
LOGI("Producer: {age: %d, name: %s}", student.age, student.name);
student_queue_put(queue, student);
sleep(1);
if (finished_producer) {
Status *status = (Status *) malloc(sizeof(Status));
status->code = 1001;
status->msg = "生产者线程正常退出";
status->opaque = queue;
pthread_exit((void *) status);
}
}
}
void *consumer_run(void *userdata) {
LOGE("消费者线程启动成功...\n");
StudentQueue *queue = (StudentQueue *) userdata;
while (1) {
Student student;
student_queue_get(queue, &student);
sleep(1);
LOGE("Consumer: {age: %d, name: %s}", student.age, student.name);
if (finished_consumer) {
Status *status = (Status *) malloc(sizeof(Status));
status->code = 1001;
status->msg = "消费者线程正常退出";
status->opaque = queue;
pthread_exit((void *) status);
}
}
}
extern "C"
JNIEXPORT void JNICALL
Java_me_learn_JNIThread_start(JNIEnv *env, jobject instance) {
StudentQueue *queue = (StudentQueue *) malloc(sizeof(StudentQueue));
student_queue_init(queue);
pthread_create(&producer, NULL, producer_run, (void *) queue);
pthread_setname_np(producer, "producer");
pthread_create(&consumer, NULL, consumer_run, (void *) queue);
pthread_setname_np(consumer, "consumer");
}
extern "C"
JNIEXPORT void JNICALL
Java_me_learn_JNIThread_stop(JNIEnv *env, jobject instance) {
finished_producer = 1;
finished_consumer = 1;
void *status_producer;
pthread_join(producer, &status_producer);
Status *ret_producer = (Status *) status_producer;
LOGE("[%d]: %s", ret_producer->code, ret_producer->msg);
free(ret_producer);
void *status_consumer;
pthread_join(consumer, &status_consumer);
Status *ret_consumer = (Status *) status_consumer;
LOGE("[%d]: %s", ret_consumer->code, ret_consumer->msg);
free(ret_consumer);
student_queue_destroy((StudentQueue *) ret_consumer->opaque);
producer = 0;
consumer = 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,是自己反傻了,原来finish标识设置为1之后,再次start的时候没有重新置为0...