读者 - C 语言的作者 - 我哪里错了?

Readers - writers in C - where am I wrong?

我想寻求有关此任务的帮助。

我的任务是用 C 编写一个简单的程序来模拟 readers-writers 问题。计划要求是:

  1. 程序启动后,将要求用户输入作者数和readers。

  2. 程序将不断通知用户有关线程的状态。

  3. 程序结束后,小统计(每个reader读取和每个写入写入的次数)。

我已经做了一些程序的基本结构(通过信号量等处理临界区),但是我觉得程序没有做的,应该做的。程序运行没有错误或意外行为,但计数,每次 reader 读取和每次写入的次数始终对应每个 reader 或写入器)。

我哪里错了?可能是我没看懂任务

非常感谢您的回复。

程序代码:

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

sem_t w;    // write access
sem_t m;    // mutex
int rc=0;   // readers count

int writersCount;
int readersCount;
pthread_t writersThread[10], readersThread[10];
int writeCount[10], readCount[10];
int i;

void *writer(void *i) {
    int a = *((int *) i);

    sem_wait(&w);   // P(w)
    printf("Writer %d writes to DB.\n",a+1);
    writeCount[a+1]++;  
    sem_post(&w);   // V(w)

    free(i);
}

void *reader(void *i) {
    int a = *((int *) i);

    sem_wait(&m);   // P(m)
    rc++;
    if (rc == 1) {
        sem_wait(&w);   // P(w)
    }
    sem_post(&m);   // V (m)

    printf("Reader %d reads from DB.\n",a+1);
    readCount[a+1]++;   

    sem_wait(&m);   // P(m)
    rc--;
    if (rc == 0) {
        sem_post(&w);   // V(w)
    }
    sem_post(&m);   // V(m)

    free(i);
}

int main() {
    sem_init(&w,0,1);
    sem_init(&m,0,1);

    printf("Enter count of writers:");
    scanf("%d",&writersCount);
    printf("Enter count of readers:");
    scanf("%d",&readersCount);

    for (i=0; i<readersCount; i++) {
        int *arg = malloc(sizeof(*arg));
        *arg = i;
        pthread_create(&readersThread[i], NULL, reader, arg);
    }
    for (i=0; i<writersCount; i++) {
        int *arg = malloc(sizeof(*arg));
        *arg = i;
        pthread_create(&writersThread[i], NULL, writer, arg);
    }
    for (i=0; i<writersCount; i++) {
        pthread_join(writersThread[i], NULL);
    }   
    for (i=0; i<readersCount; i++) {
        pthread_join(readersThread[i], NULL);
    }

    printf("--------------\n");
    for (i=0; i<readersCount; i++) {
        printf("Reader %d read %d times\n",i+1,readCount[i+1]);
    }

    for (i=0; i<writersCount; i++) {
        printf("Writer %d wrote %d times\n",i+1,writeCount[i+1]);
    }

    sem_destroy(&w);
    sem_destroy(&m);
    return 0;
}

输出: 输入 writers:4 的计数 输入 readers:4

的计数
Reader 1 reads from DB.
Reader 3 reads from DB.
Reader 4 reads from DB.
Reader 2 reads from DB.
Writer 1 writes to DB.
Writer 2 writes to DB.
Writer 3 writes to DB.
Writer 4 writes to DB.
--------------
Reader 1 read 1 times
Reader 2 read 1 times
Reader 3 read 1 times
Reader 4 read 1 times
Writer 1 wrote 1 times
Writer 2 wrote 1 times
Writer 3 wrote 1 times
Writer 4 wrote 1 times

您的输出完全正确,因为您 运行 的每个线程都只执行一个 read/write。在 reader/writer 函数中放置一些循环来改变这个事实。当您 运行 有 10 个读者或作者时,您的程序可能会遇到错误,因为他们中的一个会尝试访问 writeCount[10]readCount[10],更改它并且您有一个正确的程序。

你可以试试这个,但是请选择 vasicbre 的答案,因为他是第一个发现问题的人。

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

sem_t w;    // write access
sem_t m;    // mutex
int rc=0;   // readers count

int writersCount;
int readersCount;
pthread_t writersThread[100], readersThread[100];
int writeCount[10], readCount[10];

void *writer(void *i)
{
    int a = *((int *) i);

    sem_wait(&w);   // P(w)
    printf("Writer %d writes to DB.\n",a+1);
    writeCount[a + 1]++;
    sem_post(&w);   // V(w)

    return NULL;
}

void *reader(void *i)
{
    int a = *((int *) i);

    sem_wait(&m);   // P(m)
    rc++;
    if (rc == 1) {
        sem_wait(&w);   // P(w)
    }
    sem_post(&m);   // V (m)

    printf("Reader %d reads from DB.\n", a + 1);
    readCount[a + 1]++;

    sem_wait(&m);   // P(m)
    rc--;
    if (rc == 0) {
        sem_post(&w);   // V(w)
    }
    sem_post(&m);   // V(m)

    return NULL;
}

int randomCount()
{
    return 5.0 * rand() / RAND_MAX;
}

int main()
{
    sem_init(&w,0,1);
    sem_init(&m,0,1);

    int i;

    printf("Enter count of writers:");
    scanf("%d",&writersCount);
    printf("Enter count of readers:");
    scanf("%d",&readersCount);

    int readerIndices[readersCount];
    int writerIndices[writersCount];
    int totalReaders = 0;
    int totalWriters = 0;

    for (i=0; i<readersCount; i++)
    {
        int j;
        int count;

        readerIndices[i] = i;
        count            = randomCount();
        for (j = 0 ; j < count ; ++j)
        {
            pthread_create(&readersThread[totalReaders++], NULL, reader, &readerIndices[i]);
        }
    }

    for (i = 0 ; i < writersCount ; i++)
    {
        int j;
        int count;

        writerIndices[i] = i;
        count            = randomCount();
        for (j = 0 ; j < count ; ++j)
        {
            pthread_create(&writersThread[totalWriters++], NULL, writer, &writerIndices[i]);
        }
    }

    for (i = 0 ; i < totalWriters ; i++)
    {
        pthread_join(writersThread[i], NULL);
    }

    for (i = 0 ; i < totalReaders ; i++)
    {
        pthread_join(readersThread[i], NULL);
    }

    printf("--------------\n");
    for (i = 0 ; i < readersCount ; i++)
    {
        printf("Reader %d read %d times\n", i + 1, readCount[i + 1]);
    }

    for (i = 0 ; i < writersCount ; i++)
    {
        printf("Writer %d wrote %d times\n", i + 1, readCount[i + 1]);
    }

    sem_destroy(&w);
    sem_destroy(&m);
    return 0;
}