0

this is code:

class program
{
    static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
    static void Main(string[] args)
    {
        for (int i = 0; i < 2; i++)
        {
            Task.Factory.StartNew(Read);
        }
        for (int i = 0; i < 1; i++)
        {
            Task.Factory.StartNew(Write);
        }
        Console.Read();
    }

    static void Read()
    {
        while (true)
        {
            rwLock.EnterReadLock();;
            Thread.Sleep(100);
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}  reading");
            rwLock.ExitReadLock();
        }
    }
    static void Write()
    {
        while (true)
        {
            rwLock.EnterWriteLock();
            Thread.Sleep(3000);
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} writing");
            rwLock.ExitWriteLock();
        }
    }
}

I want to test the ReaderWriterLockSlim, the result what I expect is read and write alternately in console, but at last, there only write in console.

Here the result:

5 reading 2020/2/17 18:24:36
4 reading 2020/2/17 18:24:36
3 reading 2020/2/17 18:24:36
6 writing 2020/2/17 18:24:39
6 writing 2020/2/17 18:24:42
6 writing 2020/2/17 18:24:45
6 writing 2020/2/17 18:24:48
6 writing 2020/2/17 18:24:51
6 writing 2020/2/17 18:24:54
6 writing 2020/2/17 18:24:57
6 writing 2020/2/17 18:25:00
6 writing 2020/2/17 18:25:03
6 writing 2020/2/17 18:25:06

but when use ReaderWriterLock, its alternate display. Here the result:

4 reading 2020/2/17 18:30:22
3 reading 2020/2/17 18:30:22
5 reading 2020/2/17 18:30:22
6 writing 2020/2/17 18:30:25
4 reading 2020/2/17 18:30:25
3 reading 2020/2/17 18:30:25
5 reading 2020/2/17 18:30:25
6 writing 2020/2/17 18:30:28
4 reading 2020/2/17 18:30:29
5 reading 2020/2/17 18:30:29
3 reading 2020/2/17 18:30:29
6 writing 2020/2/17 18:30:32
4 reading 2020/2/17 18:30:32
5 reading 2020/2/17 18:30:32
3 reading 2020/2/17 18:30:32
6 writing 2020/2/17 18:30:35
5 reading 2020/2/17 18:30:35
3 reading 2020/2/17 18:30:35
4 reading 2020/2/17 18:30:35
6 writing 2020/2/17 18:30:38
5 reading 2020/2/17 18:30:45
3 reading 2020/2/17 18:30:45
4 reading 2020/2/17 18:30:45

Why does this happen, someone tell me the reason for this phenomenon? Hope answer

jzian
  • 23
  • 5
  • this *seems* like a question of "fairness policy"; see the [remarks here](https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim?view=netframework-4.8) - it *suggests* that the net48 policy tries to balance writers and readers; what exact framework are you on here? it also says, however, that as long as there is a single thread in write mode or trying to enter write mode, threads in read mode are blocked... – Marc Gravell Feb 17 '20 at 10:44
  • Yes, I want to express is read mode are blocked – jzian Feb 17 '20 at 11:28
  • This is a locking problem called *starvation*. There is an extremely short amount of time available to a reader to acquire the lock. And RWLS favors writers and starves readers, as described in [this blog post](http://joeduffyblog.com/2007/03/29/on-the-imperfect-nature-of-readerwriter-lock-policies/). – Hans Passant Feb 17 '20 at 16:50

1 Answers1

0

The problems here is that thread.Sleep() is called whilst inside the critical section. this causes the writer thread to hold the lock for periods of 3 secs each time and releases it for a very small amount of time in which the writer thread re-acquires the lock as, in this case apparently, ReaderWriterLockSlim gives better priority to writers.

I tried calling Thread.Sleep() after releasing the lock and everything works as expected.

class LockProgram
{
    static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
    static void Main(string[] args)
    {
        for (int i = 0; i < 2; i++)
        {
            Task.Factory.StartNew(Read);
        }
        for (int i = 0; i < 1; i++)
        {
            Task.Factory.StartNew(Write);
        }
        Console.Read();
    }

    static void Read()
    {
        while (true)
        {
            rwLock.EnterReadLock(); ;                
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}  reading");
            rwLock.ExitReadLock();
            Thread.Sleep(100);
        }
    }
    static void Write()
    {
        while (true)
        {
            rwLock.EnterWriteLock();                
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} writing");
            rwLock.ExitWriteLock();
            Thread.Sleep(3000);
        }
    }
}

It's worth checking out the .Net reference source for ReaderWriterLockSlim and ReaderWriterLock

Assaf
  • 316
  • 2
  • 6