readers-writers problems

In computer science, the first and second readers-writers problems are examples of a common computing problem in concurrency. The two problems deal with situations in which many threads must access the same shared memory at one time, some reading and some writing, with the natural constraint that no process may access the share for reading or writing while another process is in the act of writing to it. (In particular, it is allowed for two or more readers to access the share at the same time.) A readers-writer lock is a data structure that solves one or more of the readers-writers problems.

The first readers-writers problem[edit]

Suppose we have a shared memory area with the constraints detailed above. It is possible to protect the shared data behind a mutual exclusion mutex, in which case no two threads can access the data at the same time. However, this solution is suboptimal, because it is possible that a reader R1 might have the lock, and then another reader R2 requests access. It would be foolish for R2 to wait until R1 was done before starting its own read operation; instead, R2 should start right away. This is the motivation for the first readers-writers problem, in which the constraint is added that no reader shall be kept waiting if the share is currently opened for reading. This is also called readers-preference, with its solution below:

semaphore wrt=1, mutex=1;
readcount=0;
 
writer()
{
    wait(wrt);
    // Writing is done
    signal(wrt);
}
 
reader()
{
    wait(mutex);
    readcount++;
    if (readcount == 1)
        wait(wrt);
    signal(mutex);
    // Do the Reading
    // (Critical Section Area)
    wait(mutex);
    readcount--;
    if (readcount == 0)
        signal(wrt);
    signal(mutex);
}

The second readers-writers problem[edit]

Suppose we have a shared memory area protected by a mutex, as above. This solution is suboptimal, because it is possible that a reader R1 might have the lock, a writer W be waiting for the lock, and then a reader R2 requests access. It would be foolish for R2 to jump in immediately, ahead of W; if that happened often enough, W would starve. Instead, W should start as soon as possible. This is the motivation for the second readers-writers problem, in which the constraint is added that no writer, once added to the queue, shall be kept waiting longer than absolutely necessary. Here, P() is for wait and V() is for signal. This is also called writers-preference.

A solution to the writers-preference scenario is presented below:[1]

int readcount, writecount; (initial value = 0)
semaphore mutex_1, mutex_2, mutex_3, w, r ; (initial value = 1)
 
READER
  P(mutex_3);
    P(r);
      P(mutex_1);
        readcount := readcount + 1;
        if readcount = 1 then P(w);
      V(mutex_1);
    V(r);
  V(mutex_3);
 
  reading is performed
 
  P(mutex_1);
    readcount := readcount - 1;
    if readcount = 0 then V(w);
  V(mutex_1);
 
WRITER
  P(mutex_2);
    writecount := writecount + 1;
    if writecount = 1 then P(r);
  V(mutex_2);
 
  P(w);
    writing is performed
  V(w);
 
  P(mutex_2);
    writecount := writecount - 1;
    if writecount = 0 then V(r);
  V(mutex_2);

The third readers-writers problem[edit]

In fact, the solutions implied by both problem statements result in starvation — the first readers-writers problem may starve writers in the queue, and the second readers-writers problem may starve readers. Therefore, the third readers-writers problem is sometimes proposed, which adds the constraint that no thread shall be allowed to starve; that is, the operation of obtaining a lock on the shared data will always terminate in a bounded amount of time.

A solution with fairness for both readers and writers might be as follows:

        semaphores: no_waiting, no_accessing, counter_mutex ( initial value is 1 ) 
        shared variables: nreaders ( initial value is 0 ) 
        local variables:  prev, current
 
WRITER:
        P( no_waiting );
        P( no_accessing );
        V( no_waiting );
          ...  write ...
        V( no_accessing );
 
READER:
        P( no_waiting );
          P( counter_mutex );
            prev := nreaders;
            nreaders := nreaders + 1;
          V( counter_mutex );
          if prev = 0  then P( no_accessing );
        V( no_waiting );
        ... read ...
        P( counter_mutex );
          nreaders := nreaders - 1;
          current := nreaders;
        V( counter_mutex );
        if current = 0 then V( no_accessing );

Note that sections protected by counter_mutex could be replaced by a suitable fetch-and-add atomic instruction, saving two potential context switches in reader's code.

Note also that this solution can only satisfy the condition that "no thread shall be allowed to starve" if and only if semaphores preserve first-in first-out ordering when blocking and releasing threads. Otherwise, a blocked writer, for example, may remain blocked indefinitely with a cycle of other writers decrementing the semaphore before it can.

See also[edit]

References[edit]

[2] [3] [4]

  1. Jump up ^ Communications of the ACM :Concurrent Control with "Readers" and "Writers" P.J. Courtois,* F. H, 1971 [1]
  2. Jump up ^ Morris JM (1979) A starvation-free solution to the mutual exclusion problem. Inf Process Lett 8:76–80
  3. Jump up ^ Fair Solution to the Reader-Writer-Problem with Semaphores only. H. Ballhausen, 2003 [2]
  4. Jump up ^ Faster Fair Solution for the Reader-Writer Problem. V.Popov, O.Mazonka 2013 [3]

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值