多线程生产者-消费者模型实现文件单词提取 - C语言 OpenMP 示例
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <omp.h> #define MAX_LINE_SIZE 1024 #define MAX_WORD_SIZE 128 #define QUEUE_SIZE 100 // 共享队列 char* queue[QUEUE_SIZE]; int front = 0; int rear = 0; int count = 0; // 生产者 void producer(char* filename) { FILE* file = fopen(filename, "r"); if (file == NULL) { printf("Error opening file: %s\n", filename); return; } char line[MAX_LINE_SIZE]; while (fgets(line, sizeof(line), file)) { char* new_line = strdup(line); // 复制一份文本行 #pragma omp critical // 保证队列操作的原子性 { while (count == QUEUE_SIZE) { #pragma omp flush(count) } queue[rear] = new_line; // 插入队列 rear = (rear + 1) % QUEUE_SIZE; count++; #pragma omp flush(rear, count) } } fclose(file); } // 消费者 void consumer() { while (1) { char* line; #pragma omp critical // 保证队列操作的原子性 { while (count == 0) { #pragma omp flush(count) } line = queue[front]; // 取出队列首元素 front = (front + 1) % QUEUE_SIZE; count--; #pragma omp flush(front, count) } char* word = strtok(line, " \t\n"); while (word != NULL) { printf("Word: %s\n", word); // 输出单词 word = strtok(NULL, " \t\n"); } free(line); } } int main() { char* filenames[] = {"file1.txt", "file2.txt", "file3.txt"}; int num_files = sizeof(filenames) / sizeof(filenames[0]);
#pragma omp parallel num_threads(num_files + 1)
{
int thread_id = omp_get_thread_num();
if (thread_id < num_files) {
producer(filenames[thread_id]);
} else {
consumer();
}
}
return 0;
} 该程序使用了生产者-消费者模型来处理多个文件中的单词。程序使用多线程来同时处理多个文件。
程序中的生产者函数producer负责读取文件中的文本行,并将每一行复制到共享队列中。生产者使用strdup函数来复制一份文本行,以避免竞争条件。
程序中的消费者函数consumer负责从共享队列中取出文本行,并将每一行按空格、制表符和换行符进行分割,提取出单词并输出。消费者使用strtok函数来分割文本行。
在主函数中,使用#pragma omp parallel指令创建多个线程。其中,前面的线程被指定为生产者,负责调用producer函数读取文件并将文本行插入到队列中;最后一个线程被指定为消费者,负责调用consumer函数从队列中取出文本行并处理。
通过使用#pragma omp critical指令,程序保证了对共享队列的操作是原子的,避免了竞争条件。使用#pragma omp flush指令来保证对计数变量的修改对其他线程可见。
最后,程序使用三个文件名作为输入,并根据文件数创建对应数量的线程来处理文件。
原文地址: https://www.cveoy.top/t/topic/pUMp 著作权归作者所有。请勿转载和采集!