816161 and/or ReaderWriterLock thread example help.

First off, forget my lack of full understanding of thread locking.  Please do not suggest the C# LOCK method, I am aware of this feature.  I am trying to understand the ReaderWriterLock methods available.  The Microsoft Support article 816161 This just does not look right to me.  What am I missing?  Here is the suggestioned ReaderWriterLock example.

namespace MultiThreadApplication
{
  class Class1
  {
    private ReaderWriterLock rwl = new ReaderWriterLock();
    private int myNumber;
    public int Number   // the Number property
    {
      get
      {
        rwl.AcquireReaderLock(Timeout.Infinite);                
        try
        {
          Thread.Sleep(50);  //What is this doing here?
        }
        finally
        {
          rwl.ReleaseReaderLock();
        }
        return myNumber;
      }
      set
      {
        rwl.AcquireWriterLock(Timeout.Infinite);
        try
        {
          Thread.Sleep(50);     // again with the sleeping!!??
          myNumber = value;
        }
        finally
        {
          rwl.ReleaseWriterLock();
        }      }    }  }}  // So I don't take endless pages on EE

LVL 4
ErikPhilipsAsked:
Who is Participating?
 
AlexFMCommented:
Yes, your code is correct. When I answered your question, I didn't pay attention to the difference between your and MS code.
0
 
ErikPhilipsAuthor Commented:
Alright, I could be way off, but with the above example, the lock is released before the return?  Isn't it theoretically possible (especially on a multiple processor machine) for a write to occur between the ReleaseReaderLock and the return mynumber, however unprobable?  Could less error prone code look like the following?  Or am I completely whacked, and I am just not getting it? :)

namespace MultiThreadApplication
{
  class Class1
  {
    private ReaderWriterLock rwl = new ReaderWriterLock();
    private int myNumber;
    public int Number   // the Number property
    {
      get
      {
        rwl.AcquireReaderLock(Timeout.Infinite);                
        try
        {
          int result = myNumber;          
        }
        finally
        {
          rwl.ReleaseReaderLock();
        }
        return result;
      }
      set
      {
        rwl.AcquireWriterLock(Timeout.Infinite);
        try
        {
          myNumber = value;
        }
        finally
        {
          rwl.ReleaseWriterLock();
        }      }    }  }}  // :)
0
 
AlexFMCommented:
finally block is executed in any case: both if exception occured or not. Lock is released always.
Thread.Sleep is used for testing purposes - if you want to write multi-threaded application which uses this class, you need to test this class for thread safety. However, without Sleep get and set methods time is so short that program is working correctly also without  ReaderWriterLock. Real program may execute some processing in the code fragment protected by ReaderWriterLock, for example, read/write some array. Sleep emulates such situation.

Write may occur after release of ReleaseReaderLock and returning the result. But this is OK, get method returns value which is valid at the time of get call. After get call value may be changed by writer.

0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

 
AlexFMCommented:
AcquireReaderLock and AcquireWriterLock are used with Timeout.Infinite parameter. If some thread calls AcquireWriterLock and doesn't call ReleaseWriterLock, any other thread which calls AcquireWriterLock is locked. The only way to exit from deadlock is to call Thread.Abort, whicha caused exception in currently executed code. This is a reason of using try block in this code fragment.
0
 
ErikPhilipsAuthor Commented:
I completely understand making sure the Lock is always released.  Bad things have... could have happend if I did't do that. :)

I also understand the infinite wait period.  I may not have asked my question to the proper detail.

the MS Example looks like to me is it acquires a reader lock, the releases it, then returns the value mynumber.  Where as what my Example looks like is acquire a lock, read the value into local variable, release the lock, return the local variable.  It appears my would leave no room for a write/read error.  Is this correct?

 get  //MS Example
      {
        rwl.AcquireReaderLock(Timeout.Infinite);                
        try
        {
          Thread.Sleep(50);
        }
        finally
        {
          rwl.ReleaseReaderLock();
        }
        return myNumber;

 get // my Example
      {
        rwl.AcquireReaderLock(Timeout.Infinite);                
        try
        {
          int result = myNumber;          
        }
        finally
        {
          rwl.ReleaseReaderLock();
        }
        return result;
0
 
ErikPhilipsAuthor Commented:
BAD MS!!!
0
 
AlexFMCommented:
"Write may occur after release of ReleaseReaderLock and returning the result. But this is OK, get method returns value which is valid at the time of get call. After get call value may be changed by writer."

This was written reading your code:

      get
      {
        rwl.AcquireReaderLock(Timeout.Infinite);                
        try
        {
          int result = myNumber;          
        }
        finally
        {
          rwl.ReleaseReaderLock();
        }
        return result;
      }

and not MS code from the first post. MS code is wrong.
0
 
ErikPhilipsAuthor Commented:
I understand what you are saying, but sometimes it may not be the value I was expecting.  After all, if 4 threads have read locks, and a 5th is waiting on a writelock, and I need those 4 threads to have the same value on the last read before the write, the MS code example may not follow that rule.
0
 
ErikPhilipsAuthor Commented:
Wait a sec, my code doesn't WORK!!!  What the...

MultiThreadApplication.cs(33): The name 'result' does not exist in the class or namespace MultiThreadApplication.Class1

hahaha  I didn't know when you scoped varibles, that it would actually scope the variable "INSIDE" the try statement... the following works

      get
      {
        rwl.AcquireReaderLock(Timeout.Infinite);                
        int result;
        try
        {
          result = myNumber;          
        }
        finally
        {
          rwl.ReleaseReaderLock();
        }
        return result;
      }
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.