Question about ReaderWriterLock

G

Guest

Hi Everybody,

I've got a question about ReaderWriterLock:

Let's say I want to write a function that will update an object under write
lock
both if the calling thread has a reader lock or not.

That Is, I want a function Write() that will work properly in both these
cases:

static int i=0;

static public ReaderWriterLock locker=new ReaderWriterLock();

static public void Main() {
Write(0); // write to i outside reader lock.

locker.AquireReaderLock();
Write(i*2); // write to i unside reader lock.
locker.ReleaseReaderLock();
}

The only way I could think to write the function is something like this:

static public void Write(int val)
{
System.Threading.LockCookie cookie=new
System.Threading.LockCookie();
bool upgraded=false;
if (locker.IsReaderLockHeld)
{
cookie= locker.UpgradeToWriterLock(5000);
upgraded=true;
}
else
{
locker.AcquireWriterLock(5000);
}
try
{
i=val;
}
finally
{
if (upgraded)
{
locker.DowngradeFromWriterLock(ref cookie);
}
else
{
locker.ReleaseWriterLock();
}
}
}

This seems to do the work, but the code is a bit... complicated..

Why does locker.AquireWriteLock() inside a reader lock block?
This does not make much sense to me...

Thanks,
Nadav
 
J

Jeffrey Tan[MSFT]

Hi Nadav,

Based on my understanding, you want to know about why ReaderWriterLock does
not allow AcquireWriteLock to be called when the same thread has already
acquired the reader lock. If I have misunderstood you, please feel free to
tell me, thanks.

Yes, your code logic is the correct programming style regarding
ReaderWriterLock class. This will eliminate the potential deadlock.

I think this requirement is by the design of the semantic. In
"ReaderWriterLock Class" description, you can see that "A thread can hold a
reader lock or a writer lock, but not both at the same time". So the
ReaderWriterLock class design semantic does not allow a thread to acquire
both reader lock and writer lock. Under this the design principle, if
ReaderWriterLock allows you to acquire the writer clock while it is holding
reader lock now, then this thread has the reader/writer lock at the same
time, which will violate the semantic above.

Ok, let's take another pratical example:

We have 3 methods: BeginUpdateRead, EndUpdateRead, UpdateWrite.
"BeginUpdateRead" will acquire the reader lock and start read the protected
resource while "EndUpdateRead" will finish the remind read operations to
the protected resource and release the reader lock. "UpdateWrite" will
acquire the writer lock and modify the protected resource and release the
writer.

Now, in the single thread, we are calling the 3 methods:
BeginUpdateRead
UpdateWrite
EndUpdateRead

Note: we are using ReaderWriterLock to protect the shared resource, it
means that we want to keep the modification to the shared resource as an
atomic operation.

"BeginUpdateRead" partially reads state #1 of the shared resource. Then if
UpdateWrite succeeded with getting the writer lock, it will update the
shared resource to state #2, then EndUpdateRead will finally read the
remind state #2 of shared resource. So the reader will get the data mixed
with state #1 and #2, which will violate the usage of ReaderWriterLock. So
the ReaderWriterLock does not allow a thread to acquire the reader and
writer lock at the same time.

Hope it helps!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi Jeffrey,
I think this requirement is by the design of the semantic. In
"ReaderWriterLock Class" description, you can see that "A thread can hold a
reader lock or a writer lock, but not both at the same time". So the
ReaderWriterLock class design semantic does not allow a thread to acquire
both reader lock and writer lock. Under this the design principle, if
ReaderWriterLock allows you to acquire the writer clock while it is holding
reader lock now, then this thread has the reader/writer lock at the same
time, which will violate the semantic above.

First of all, if this is a design decision, I think it would be better for
ReaderWriterLock to throw an exception if trying to aquire Writer Lock when
Reader lock is held by the same thread instead of deadlocking the application.
BeginUpdateRead
UpdateWrite
EndUpdateRead

BeginUpdateRead/EndUpdateRead sounds like Async operation that whould
execute on another thread (unless I'm very confused) so why would you lock
the ReaderWriterLock on the original thread?
And even if you do lock on the original thread, you can still use
UpgradeToWriterLock to get a Writer Lock, so the problem still exists.

Nadav
 
J

Jeffrey Tan[MSFT]

Hi Nadav,

Thanks for your feedback.

#1, yes, your suggestion of throwing exception makes sense. However, the
current .Net implementation does not take the exception approach of
notifying the developer yet. I will help to forward your suggestion. You
may also submit this suggestion in the product feedback center below to
increase the priority:
https://connect.microsoft.com/content/content.aspx?ContentID=2220&wa=wsignin
1.0&siteid=-2

#2, sorry, I think there is some confusion in the naming of the methods.
The BeginUpdateRead/EndUpdateRead in my sample are not the asychronous
operations. They are 2 steps normal methods that read the protected share
resource. "BeginUpdateRead" acquires the lock and reads first part of the
shared resource, while the "UpdateWrite" is called to acquire the writer
lock and modify the shared resource. Finally, "EndUpdateRead" reads the
other part of the shared resource to finish the reading logic. In this
process, the read operation will read the whole shared resource with one
part with the old data and the other party with the modified data. So this
will break the atom read logic.

The reason I provide this example is that: in the scenario of acquiring a
writer lock while holding the reader lock, it means that you still want to
read the shared resource sometime after the writer lock(or, you may just
release the reader lock and then acquire the writer lock). So there will be
some additional read operation over the shared resource(EndUpdateRead).

Hope this is clear to you now. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi Jeffrey,
#2, sorry, I think there is some confusion in the naming of the methods.
The BeginUpdateRead/EndUpdateRead in my sample are not the asychronous
operations. They are 2 steps normal methods that read the protected share
resource. "BeginUpdateRead" acquires the lock and reads first part of the
shared resource, while the "UpdateWrite" is called to acquire the writer
lock and modify the shared resource. Finally, "EndUpdateRead" reads the
other part of the shared resource to finish the reading logic. In this
process, the read operation will read the whole shared resource with one
part with the old data and the other party with the modified data. So this
will break the atom read logic.

The reason I provide this example is that: in the scenario of acquiring a
writer lock while holding the reader lock, it means that you still want to
read the shared resource sometime after the writer lock(or, you may just
release the reader lock and then acquire the writer lock). So there will be
some additional read operation over the shared resource(EndUpdateRead).

So the Same code, on the same thread, calls a function that aquired a read
lock,
Then calls a function that aquires a write lock and does some changes, and
attempts to continue reading from the object and reads inconsistant data?
This has nothing to do with locks or threads!
Locks are supposed to prevent OTHER threads from modifing your data.

Nadav
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top