【问题标题】:Reader Writer with a monitor带显示器的读写器
【发布时间】:2017-11-11 01:28:52
【问题描述】:

我正在使用 pthreads 库来尝试实现带有监视器的读取器/写入器应用程序。

我主要通过以下方式调用我的线程函数

pthread_t *tid;
tid = (pthread_t*)malloc(sizeof(pthread_t)*(r + w));
int addr = 0;
//Create r # readers
for (int a = 0; a < r; a++)
{
    pthread_create(&tid[addr], NULL, Reader, (void*)&a);
    addr++;
}

然后它们通过以下3个函数调用完成它们的功能

void *Reader(void *pid)
{
    static int *id = (int*)pid;
    for (int i = 0; i < 10; i++)
    {
        beginRead(id);
        endRead();
        #ifdef __unix
            usleep(R);
        #endif
        #ifdef _WIN32
            Sleep(R);
        #endif
    }
    return 0;
}

void beginRead(int *id)
{
    //If writelock or writer_queued then wait(canRead)
    pthread_mutex_lock(&writelock);
    while (writer_queued)
    {
        reader_queued = true;
        pthread_cond_wait(&canRead, &writelock);
        reader_queued = false;
    }
    readers++;
    pthread_mutex_unlock(&writelock);
    pthread_mutex_lock(&output);
    time_t t = time(0);
    struct tm * now = localtime(&t);
    fprintf(outputfile, "DB value read =:%d:%d by reader number: %d\n", now-        >tm_sec, (now->tm_sec) / 1000, (int)*id);
    printf("DB value read =:%d:%d by reader number: %d\n", now->tm_sec, (now->tm_sec)/1000, (int)*id);
    pthread_mutex_unlock(&output);
    pthread_cond_broadcast(&canRead);
}

void endRead()
{
    --readers; // just finished a reader
    if (readers == 0)
    {
        pthread_cond_signal(&canWrite);
    }
}

这应该使每个线程进入代码的关键部分 10 次(所以如果创建了 2 个线程,它将访问关键部分 20 次)我让线程访问我的代码的关键部分正确的次数,我就是无法让它打印出正确的线程 ID#

所以如果我用 r=2 和 R=200 调用这个函数,我的输出将是:

DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2

什么时候应该是这样的

DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number:1
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2
DB value read =:30:0 by reader number: 2

取决于每个线程访问临界区的时间

【问题讨论】:

  • Reader 之后是 2 个打开和 3 个关闭。 endRead 有 2 个打开和 1 个关闭。
  • 代码将同一个地址a的地址)传递给每个 b> 线程。
  • OT:没有必要在 C 中强制转换 void-Pointers。

标签: c pthreads monitor


【解决方案1】:

代码将同一个地址a的地址)传递给每个线程。

您想将单独的地址传递给每个线程。

您可以这样做,例如:

struct thread_info
{
  pthread_t tid;
  int id;
}

...

  struct thread_info * pti = malloc((r + w) * sizeof *pit);
  size_t addr = 0;

  //Create r # readers
  for (int a = 0; a < r; a++)
  {
    pti[addr]->id = a;
    pthread_create(&pti[addr]->tid, NULL, Reader, &pti[addr]->id);

    addr++;
  }

还有这一行

  --readers; // just finished a reader

同时访问 readers 不受保护。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    相关资源
    最近更新 更多