Roman Uvarov

I found strange behaviour for ReaderWriterLock. If I call method AcquireWriterLock and then after this in the same thread call method AcquireReaderLock with ReleaseReaderLock, method RelaseWriterLock will not release ReaderWriterLock and WriterLock will stay alive.

Is anybody know is this a bug or a feature

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;

namespace QuickTest
{
static class Program
{
private static ReaderWriterLock _rwl = new ReaderWriterLock();
/// <summary>
/// The main entry point for the application.
/// </summary>
[MTAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

TestReaderTimeOutException();

}

private static void TestReaderTimeOutException()
{

//1. Make thread which will lock ReaderWriteLock
Thread thre = new Thread(new ThreadStart(LockWriter));
thre.Start();

//2. Make thread whick try to acquire ReaderWriteLock and throw timeout
Thread thre2 = new Thread(new ThreadStart(LockReader));
thre2.Start();

//Wait 60 second
thre.Join();

}


private static void LockWriter()
{
try
{
_rwl.AcquireWriterLock(10000);

LockReader();

}
finally
{
if (_rwl.IsWriterLockHeld)
{
_rwl.ReleaseWriterLock(); //NOT RELEASE WRITER LOCK!


}
}

}

private static void LockReader()
{
try
{
try
{
_rwl.AcquireReaderLock(20000);

}
finally
{
if (_rwl.IsReaderLockHeld)
{
//Try to relase lock which is not held
_rwl.ReleaseReaderLock();
}
}
}
catch (Exception ex) //!!!
{
Debug.Fail(ex.ToString());
}
finally
{
Debug.WriteLine("...");
}
}
}
}




Re: .NET Base Class Library Why ReaderWriterLock not release writer lock if inclusive read lock inside writer Lock was

nobugz

I didn't check your code, hope I got it right. AcquireReaderLock() means: "nobody can write, anybody can read". AcquireWriterLock() means: "nobody can write, nobody can read". Obviously, a much stronger lock. There would be no reason for the class to release the write lock when you call ReleaseReaderLock(), it would violate the promise made by AcquireWriterLock().





Re: .NET Base Class Library Why ReaderWriterLock not release writer lock if inclusive read lock inside writer Lock was

Roman Uvarov

But the problem is:

1. Lock Writer: IsReaderLockHeld = false, IsWriterLockHeld = true

2. Lock Reader: IsReaderLockHeld = false, IsWriterLockHeld = true

3. Release Reader: IsReaderLockHeld = false, IsWriterLockHeld = true

4. Release Writer: IsReaderLockHeld = false, IsWriterLockHeld = true

Writer will not relase if we have lock reader. This is strange...






Re: .NET Base Class Library Why ReaderWriterLock not release writer lock if inclusive read lock inside writer Lock was

Feng Chen - MSFT

Hi Roman Uvarov,

I wrote the program just like you have described, but I didn't encounter the problem as yours.

And I don't understand why you call the LockReader() in LockWriter(). You have apply a writer lock on the object, why did you continue applying reader lock on it in the same thread

And ReaderWriterLock class that encapsulates these rules:

When one thread is writing to the data, no other thread can write to the data.
When one thread is writing to the data, no other thread can read from the data.
When one thread is reading from the data, no other thread can write to the data.
When one thread is reading from the data, other threads can also read from the data.

Hope this can help you.

Thanks!






Re: .NET Base Class Library Why ReaderWriterLock not release writer lock if inclusive read lock inside writer Lock was

Roman Uvarov

May be you something wrote incorrect. I describe steps.

1. Run VS2005

2. Make new Windows Application Project

3. Find file Program.CS and replace all by using my code

4. Run and wait 20 second. You see Debug.Fail message "The operation return because timeOut period expired"

The problem is that writer is NOT RELEASE WRITER LOCK because property _rwl.IsReaderLockHeld returns false. But I am absulutely sure

writer lock is. So inclusive reader lock in the same thread definetely.

I added throw exception in code, which show where is the problem is. Just run my code and you will see

using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Text;

using System.Threading;

using System.Windows.Forms;

namespace QuickTest

{

static class Program

{

private static ReaderWriterLock _rwl = new ReaderWriterLock();

/// <summary>

/// The main entry point for the application.

/// </summary>

[MTAThread]

static void Main()

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

TestReaderTimeOutException();

}

private static void TestReaderTimeOutException()

{

//1. Make thread which will lock ReaderWriteLock

Thread thre = new Thread(new ThreadStart(LockWriter));

thre.Start();

//2. Make thread whick try to acquire ReaderWriteLock and throw timeout

Thread thre2 = new Thread(new ThreadStart(LockReader));

thre2.Start();

//Wait 60 second

thre.Join();

}

private static void LockWriter()

{

try

{

_rwl.AcquireWriterLock(5000);

LockReader();

}

finally

{

if (_rwl.IsWriterLockHeld)

{

_rwl.ReleaseWriterLock(); //NOT RELEASE WRITER LOCK!

if (_rwl.IsWriterLockHeld)

{

throw new Exception("I expect that Writer Lock is freed");

}

}

}

}

private static void LockReader()

{

try

{

try

{

_rwl.AcquireReaderLock(20000);

}

finally

{

if (_rwl.IsReaderLockHeld)

{

//Try to relase lock which is not held

_rwl.ReleaseReaderLock();

}

else

{

throw new Exception("We not free ReaderLock!!!! So ReaderWriterLock is permanetly damaged");

}

}

}

catch (Exception ex) //!!!

{

Debug.Fail(ex.ToString());

}

finally

{

Debug.WriteLine("...");

}

}

}

}






Re: .NET Base Class Library Why ReaderWriterLock not release writer lock if inclusive read lock inside writer Lock was

nobugz

The problem is that you acquire a read lock while you already have the write lock. From the "Note" section of the AcquireReadLock() documentation:

If the current thread already has the writer lock, no reader lock is acquired. Instead, the lock count on the writer lock is incremented. This prevents a thread from blocking on its own writer lock. The result is exactly the same as calling AcquireWriterLock, and an additional call to ReleaseWriterLock is required when releasing the writer lock.

In other words, LockReader() in the "thre" thread will not get a reader lock but an extra writer lock. You'll bomb when you test only for IsReaderLockHeld. Change the finally clause in LockReader like this:

finally {
if (_rwl.IsReaderLockHeld || _rwl.IsWriterLockHeld) {
_rwl.ReleaseReaderLock();
}

The normal use for ReaderWriterLock is for just one thread doing the writing and no reading, many threads doing the reading. You can make your usage consistent by simply not acquiring the reader lock if you already hold the writer lock.





Re: .NET Base Class Library Why ReaderWriterLock not release writer lock if inclusive read lock inside writer Lock was

Roman Uvarov

Yes. You are absolutely right!

I was light-headed man, i missed this note and be entrapped of myself inattention to detail...