【问题标题】:reader-writer accessing multiple readers读写器访问多个读者
【发布时间】:2015-01-09 20:51:30
【问题描述】:

在 UNIX 中实现 WRITER-READER 问题时,我有一些问题无法解决。 第一个是我不知道,如何修改代码以像线程总是调用进入阅览室一样工作。例如,当作家在阅览室时,读者正在等待访问阅览室。当作家逃离阅览室,读者进入阅览室时,他还在等待机会。 第二个是我不知道怎么修改代码让几个读者进入阅览室。在我的代码中,阅览室中只能有一个线程同时出现。 第三个是,如何判断作者或读者是否饿了?哪一个在我的代码中挨饿?

代码如下:

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

#define READERS 15
#define WRITERS 10

int bufferw = 0, bufferr = 0, counterw = WRITERS, counterr = READERS;
int i;

pthread_mutex_t mwrite, mread;
pthread_cond_t condw, condr;
pthread_t r[READERS], w[WRITERS];

void *writer(void *ptr) {

    pthread_mutex_lock(&mwrite);

    {
      counterr = READERS;
      counterw = WRITERS;
      ++bufferw;    

     for(i=0; i<READERS; i++) while(bufferr > 0) pthread_cond_wait(&condw, &r[i]);

      printf("WRITER ENTERING!");

      pthread_mutex_unlock(&mwrite);

      bufferw--;
    }

    pthread_cond_signal(&condr);

    pthread_exit(0);
}

void *reader(void *ptr) {

    counterr = READERS;
    counterw = WRITERS;

    {
      ++bufferr;

      for(i=0; i<WRITERS; i++) while(bufferw == 1) pthread_cond_wait(&condr, &w[i]);

      printf("READER ENTERING!");

      bufferr = 0;
    }

    pthread_cond_signal(&condw);
    pthread_exit(0);
}


int main(int argc, char* argv[]) {

    pthread_mutex_init(&mwrite, 0);
    pthread_mutex_init(&mread, 0);

    pthread_cond_init(&condw, 0);
    pthread_cond_init(&condr, 0);

    for(i=0; i<WRITERS; i++) pthread_create(&w[i], NULL, writer, NULL);
    for(i=0; i<READERS; i++) pthread_create(&r[i], NULL, reader, NULL);

    for(i=0; i<WRITERS; i++) pthread_join(w[i], NULL);
    for(i=0; i<READERS; i++) pthread_join(r[i], NULL);

    pthread_cond_destroy(&condw);
    pthread_cond_destroy(&condr);
    pthread_mutex_destroy(&mwrite);
    pthread_mutex_destroy(&mread);

 return 0;
}

提前感谢您的帮助!

EDIT:// 在这种情况下如何避免比赛?

【问题讨论】:

  • 我有点迷路了。你有不写作的“作家”和不阅读的“读者”。目标是什么? (你不认为如果这两种类型的线程做了一些后果的话会更清楚吗?)
  • pthread_cond_wait 的参数在哪里定义?
  • 只是模拟。 :) 作家是一个线程,只能一个人在阅览室里,阅览室里的读者可以很多,但作家在里面就不行。 :) 他们不需要阅读或写东西。 (我想是的)。
  • @Jasen,它们是必不可少的吗?
  • 为什么不使用 pthread_rwlock_t 和相关函数?

标签: c multithreading


【解决方案1】:

您可以使用一个互斥锁和两个条件变量来实现这一点。

reader( ) {
     pthread_mutex_lock(&m);
     while (!(writers == 0))
     pthread_cond_wait(&readersQ, &m);
     readers++;
     pthread_mutex_unlock(&m);

     /* actual read */

     pthread_mutex_lock(&m);
     if (--readers == 0)
     pthread_cond_signal(&writersQ);
     pthread_mutex_unlock(&m);
    }



writer( ) {
 pthread_mutex_lock(&m);
 writers++;
 while (!((readers == 0) && (active_writers == 0))) {
 pthread_cond_wait(&writersQ, &m);
 }
 active_writers++;
 pthread_mutex_unlock(&m);

 /* actual write */

 pthread_mutex_lock(&m);
 writers--;
 active_writers--;
 if (writers > 0)
   pthread_cond_signal(&writersQ);
 else
   pthread_cond_broadcast(&readersQ);
 pthread_mutex_unlock(&m);
}

这种实现对读者是不公平的,这意味着如果有作者在写,读者将永远无法选择阅读。这是因为写作比阅读更重要。如果你不这么认为,我也可以提供一个对作者不公平的版本。

只有当 writer 等于 0 时,reader 才能选择阅读。如果只有一个写入器,写入器不会为零,读取器无法读取。

如果有多个写入者,则变量 active_writers 将确保一次只有一个写入者可以写入。

编辑

以下是饿死作家的版本。对于读者来说,它是相同的代码。

writer( ) {
 pthread_mutex_lock(&m);
 while(!((readers == 0) &&(writers == 0)))
     pthread_cond_wait(&writersQ, &m);
 writers++;
 pthread_mutex_unlock(&m);

 /* actual write */

 pthread_mutex_lock(&m);
 writers--;
 pthread_cond_signal(&writersQ);
 pthread_cond_broadcast(&readersQ);
 pthread_mutex_unlock(&m);
}

【讨论】:

  • 我实际上需要 3 个解决方案来解决这个问题:1 个让读者挨饿,1 个让作家挨饿,1 个没有挨饿,而且其中一个解决方案必须使用条件变量。 :)
  • 我提供对读者不公平的版本。我对每个人都没有一个公平的想法。
猜你喜欢
  • 2010-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-15
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多