【发布时间】:2023-04-08 07:52:01
【问题描述】:
当我在 C 中遇到读取器/写入器问题时,我正在学习 pthreads。问题非常简单,“写入器”线程将从外部源访问数据,而“读取器”线程将从共享缓冲区,然后伪处理数据。 reader 和 writer 线程需要在 while 循环中连续运行。
我正在尝试在具有 POSIX 接口的标准 unix 系统上实现和编译它。
我浏览了一些堆栈溢出问题:
Reader Writer program in C using mutexes and pthreads
而我没有得到这些。
这是我目前所拥有的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <assert.h>
#define BUFF_SIZE 50
#define M 10
#define N 20
int get_external_data(char *buffer, int bufferSizeInBytes);
void process_data(char *buffer, int bufferSizeInBytes);
int get_external_data(char *buffer, int bufferSizeInBytes){
int status;
int val;
char srcString[] = "0123456789abcdefghijklmnopqrstuvwxyxABCDEFGHIJKLMNOPQRSTUVWXYZ";
val = (int)(rand() % 62);
if (bufferSizeInBytes < val){
return (-1);
}
strncpy(buffer, srcString, val);
return val;
}
void process_data(char *buffer, int bufferSizeInBytes){
int i;
if(buffer) {
printf("thread %li - ", pthread_self());
for(i = 0; i < bufferSizeInBytes; i++) {
printf("%c", buffer[i]);
}
printf("\n");
memset(buffer, 0, bufferSizeInBytes);
} else {
printf("error in process data - %li\n", pthread_self());
}
return;
}
pthread_mutex_t data_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER;
sem_t data_count;
typedef struct node {
struct node *next;
char *data;
int length;
} node_t;
node_t *head, *tail;
/**
* This thread is responsible for pulling data off of the shared data
* area and processing it using the process_data() API.
*/
void *reader_thread(void *arg) {
int rc;
node_t *removed_node;
while(1) {
rc = sem_wait(&data_count);
if (0 != rc) {
return NULL;
}
pthread_mutex_lock(&data_lock);
assert(NULL != head);
removed_node = head;
head = head->next;
pthread_mutex_unlock(&data_lock);
//Adding this lock for sake of readability at the cost of reduced consumption rate...will run out of memory eventually.
pthread_mutex_lock(&print_lock);
process_data(removed_node->data, removed_node->length);
pthread_mutex_unlock(&print_lock);
free(removed_node->data);
free(removed_node);
}
return NULL;
}
/**
* This thread is responsible for pulling data from a device using
* the get_external_data() API and placing it into a shared area
* for later processing by one of the reader threads.
*/
void *writer_thread(void *arg) {
int length;
char *buffer;
node_t *new_node;
new_node = (node_t*) malloc(sizeof(*new_node));
buffer = (char*) malloc(sizeof(*buffer) * BUFF_SIZE);
while(1) {
length = get_external_data(buffer, BUFF_SIZE);
if (length == -1) {
//data too big, discard it and try again;
continue;
}
new_node->next = NULL;
new_node->length = length;
new_node->data = buffer;
pthread_mutex_lock(&data_lock);
if (head == NULL) { //The linked list is completely empty
head = new_node;
tail = new_node;
} else { //There are items in the list and we're appending
tail->next = new_node;
tail = new_node;
}
pthread_mutex_unlock(&data_lock);
pthread_mutex_lock(&print_lock);
printf("thread %ld wrote - %s \n", pthread_self(), buffer);
pthread_mutex_unlock(&print_lock);
sem_post(&data_count);
buffer = (char*) malloc(sizeof(*buffer) * BUFF_SIZE);
new_node = (node_t*) malloc(sizeof(*new_node));
}
return NULL;
}
int main(int argc, char **argv) {
int i = sem_init(&data_count, 0, 0);
pthread_t dummy; //creating a dummy thread
for(i = 0; i < N; i++) {
pthread_create(&dummy, NULL, reader_thread, NULL);
}
for(i = 0; i < M; i++) {
pthread_create(&dummy, NULL, writer_thread, NULL);
}
sleep(100);
return 0;
}
线程同步没有任何编译错误,但我的程序在写入器线程在缓冲区上写入几次后停止。
读取器和写入器线程需要在 while 循环中连续运行,但在我的情况下不需要。
知道如何解决这个问题吗?
【问题讨论】:
-
gcc .... -lpthread.
-
好吧,在一个返回
void *的函数中有一个没有值的返回值。返回一些东西,。 -
对于 sem_* 函数,您可能还需要 -lrt - 取决于平台
-
您的程序不会停止,因为它永远不会启动。您的构建失败并出现一些编译器警告和链接错误。