问题
第一个问题就是消费者线程并不能优雅的退出,想要的是当生产者线程退出后,消费者线程也应该退出。我这里使用了标志位发现依旧不能优雅的退出。
第二个问题就是当生产者获取用户输入后,消费者线程并不能及时消费。这个不知道怎么搞。
编译环境
系统:Windows11
工具链:mingw
IDE:Clion
代码片段
main.c
#include "stdio.h"
#include "pthread.h"
#include "buffer.h"
#include "student.h"
#define INPUT_SIZE 64
int input_count = 0;
pthread_mutex_t mutex;
pthread_cond_t input_count_cond;
void *producerThread(void *arg) {
char input[INPUT_SIZE];
queue *cb = (queue *)arg;
while (1) {
pthread_mutex_lock(&mutex);
printf("请输入数据:\n");
fflush(stdout);
if (fgets(input, INPUT_SIZE, stdin) == NULL) {
break;
}
pthread_mutex_unlock(&mutex);
if (strncmp(input, "exit", 4) == 0) {
break;
}
size_t len = strlen(input);
if (len > 0 && input[len - 1] == '\n') {
input[len - 1] = '\0';
}
static char last_char = '\0';
int i;
for (i = 0; input[i] != '\0'; ++i) {
char current_char = input[i];
if (current_char == last_char) {
continue;
}
Enqueue(cb, current_char);
pthread_mutex_lock(&mutex);
printf("在位置 %d 写入了字符 '%c'\n", (cb->tail % BUFFER_SIZE), current_char);
pthread_mutex_unlock(&mutex);
last_char = current_char;
cb->producing = 0;
pthread_cond_signal(&cb->not_empty);
}
pthread_mutex_lock(&mutex);
input_count = i;
pthread_cond_signal(&input_count_cond);
pthread_mutex_unlock(&mutex);
}
pthread_mutex_lock(&mutex);
cb->running = 0;
pthread_cond_signal(&input_count_cond);
pthread_mutex_unlock(&mutex);
return NULL;
}
void *ConsumerThread(void *arg) {
queue *cb = (queue *)arg;
char item;
char input[INPUT_SIZE];
int count = 0;
int temp_count = 0;
char class[20],lastname[NAME_LENGTH],firstname[NAME_LENGTH],id[12];
while (1) {
if (Dequeue(cb, &item)) {
pthread_mutex_lock(&mutex);
printf("在%d位置读取了字符'%c'\n", cb->head, item);
while (temp_count == 0){
pthread_cond_wait(&input_count_cond,&mutex);
temp_count = input_count;
}
pthread_mutex_unlock(&mutex);
input[count++] = item;
input[count] = '\0';
if(count == temp_count){
pthread_mutex_lock(&mutex);
if(!splitClassNameId(input,class,lastname,firstname,id)){
printf("数据解析错误!请检测输入格式!\n");
count = temp_count = 0;
memset(input,0,INPUT_SIZE);
pthread_mutex_unlock(&mutex);
continue;
}
count = temp_count = 0;
memset(input,0,INPUT_SIZE);
writeInfoToStu(&stu.stu[stu.count++],class,lastname,firstname,id);
sortStudents(&stu);
writeFirstNameToFile(stu.stu[stu.count-1]);
pthread_mutex_unlock(&mutex);
}
} else {
pthread_mutex_lock(&cb->mutex);
while (!cb->producing && cb->count == 0) {
pthread_cond_wait(&cb->not_empty, &cb->mutex);
}
pthread_mutex_unlock(&cb->mutex);
if(cb->running && cb->count == 0){
break;
}
}
}
return NULL;
}
int main() {
queue *buffer = createQueue();
InitStu();
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&input_count_cond,NULL);
pthread_t producer_thread, consumer_thread;
if (pthread_create(&producer_thread, NULL, producerThread, buffer) != 0) {
perror("pthread_create failed");
return 1;
}
if (pthread_create(&consumer_thread, NULL, ConsumerThread, buffer) != 0) {
perror("pthread_create failed");
return 1;
}
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
pthread_mutex_destroy(&buffer->mutex);
pthread_cond_destroy(&buffer->not_empty);
pthread_cond_destroy(&buffer->not_full);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&input_count_cond);
return 0;
}
buffer.c
#include "buffer.h"
queue *createQueue() {
queue *q = (queue *)malloc(sizeof(queue));
q->head = 0;
q->tail = 0;
q->count = 0;
memset(q->buffer, 0, BUFFER_SIZE);
pthread_mutex_init(&q->mutex, NULL);
pthread_cond_init(&q->not_full, NULL);
pthread_cond_init(&q->not_empty, NULL);
q->running = 1;
q->producing = 1;
return q;
}
void Enqueue(queue *q, char str) {
pthread_mutex_lock(&q->mutex);
while (q->count == BUFFER_SIZE) {
pthread_cond_wait(&q->not_full, &q->mutex);
}
q->buffer[q->tail] = str;
q->tail = (q->tail + 1) % BUFFER_SIZE;
q->count++;
pthread_cond_signal(&q->not_empty);
pthread_mutex_unlock(&q->mutex);
}
int Dequeue(queue *q, char *str) {
pthread_mutex_lock(&q->mutex);
while (q->count == 0 && q->producing) {
pthread_cond_wait(&q->not_empty, &q->mutex);
}
if (q->count > 0) {
*str = q->buffer[q->head];
q->head = (q->head + 1) % BUFFER_SIZE;
q->count--;
pthread_cond_signal(&q->not_full);
pthread_mutex_unlock(&q->mutex);
return 1;
} else {
pthread_mutex_unlock(&q->mutex);
return 0;
}
}
buffer.h
#include "stdio.h"
#include "stdbool.h"
#include "string.h"
#include "pthread.h"
#include "stdlib.h"
#define BUFFER_SIZE 64
typedef struct QUEUE{
char buffer[BUFFER_SIZE];
int head;
int tail;
int count;
pthread_mutex_t mutex;
pthread_cond_t not_full;
pthread_cond_t not_empty;
int running;
int producing;
}queue;
queue *createQueue();
void Enqueue(queue *q,char str);
int Dequeue(queue *q,char *str);