none
A global mutex-like ReaderWriterLock? RRS feed

  • Question

  • Forgive me if I posted in the wrong forum, but I didn't see one for discussions on multithreading...

    I need a way to synchronize access across app domains (and multiple user/terminal sessions) a la global mutex, but I only need to block on writes a la ReaderWriterLock. I'm relatively new at this stuff, so I don't know how to do what I need or what to use. Reading this documentation, it appears that I need to use a Mutex or WaitHandle because of my need to have this work across app domains, but I like the idea of readers not being blocked until a write needs to be done.

    Can I use the ReaderWriterLock(Slim) globally like the Mutex? If not, any suggestions on how to accomplish similar functionality using a Mutex or WaitHandle?
     

    Tuesday, July 14, 2009 9:39 PM

All replies

  • That's not how synchronization works, you cannot have thread-safe reads and only synchronized writes.  Not without some kind of dramatic advance in hardware.  ReadWriterLock blocks reads too, a call to AcquireReaderLock is required.  Since this crosses app domains, RWL is out, you need a named sync object.  Mutex should get the job done.
    Hans Passant.
    Wednesday, July 15, 2009 1:09 AM
    Moderator
  • The OP wants writers to block writers and readers, but readers should not block other readers.

    I'm pretty sure its possible to emulate a reader/writer lock with mutexes and/or events somehow, but alas don't have any code to that effect to show.
    Wednesday, July 15, 2009 1:32 AM
  • Just use two mutexes.

    Hans Passant.
    Wednesday, July 15, 2009 10:58 AM
    Moderator
  • That's not how synchronization works, you cannot have thread-safe reads and only synchronized writes.  Not without some kind of dramatic advance in hardware.  ReadWriterLock blocks reads too, a call to AcquireReaderLock is required.  Since this crosses app domains, RWL is out, you need a named sync object.  Mutex should get the job done.
    Hans Passant.

    Can you explain this a little more please? My understanding from reading the docs is that readers are not blocked until a writer gets a lock. Readers don't block other readers.

    I understand I can't use this because of my need to cross app domains, but I'd like to understand this better anyways.
    Wednesday, July 15, 2009 2:46 PM
  • The OP wants writers to block writers and readers, but readers should not block other readers.

    I'm pretty sure its possible to emulate a reader/writer lock with mutexes and/or events somehow, but alas don't have any code to that effect to show.

    Correct.
    Wednesday, July 15, 2009 2:46 PM
  • Scratch the idea of using mutexes, they have thread affinity.  I don't know how to do this either using named sync objects.  Check out this web page for ideas.

    Hans Passant.
    Wednesday, July 15, 2009 3:51 PM
    Moderator
  • On second thought, the entire premise is flaky.  App domains have their own heaps, you cannot directly read a variable from one domain in another.  Since there is no shared data between ADs, there should never be a need to lock anything.

    Hans Passant.
    Wednesday, July 15, 2009 4:00 PM
    Moderator
  • On second thought, the entire premise is flaky.  App domains have their own heaps, you cannot directly read a variable from one domain in another.  Since there is no shared data between ADs, there should never be a need to lock anything.

    Hans Passant.

    The resource is the local registry - a specific key and its children. I have encapsulated access to those keys and would like to make sure the it's thread-safe. The class library is used by different applications (mostly web apps) and so readers/writers aren't neccessarily going to be in the same app domain.

    Obviously, I'm not guaranteed that access will only be via my code, but my code will be using the class I wrote to access these values and I'd like to ensure that my readers don't get corrupted data if my writer is in the middle of updating the values.
    Wednesday, July 15, 2009 4:19 PM
  • On second thought, the entire premise is flaky.  App domains have their own heaps, you cannot directly read a variable from one domain in another.  Since there is no shared data between ADs, there should never be a need to lock anything.

    Hans Passant.

    how does the heap work for app domains? I thought all app domains in the same process share the same managed heap even though cross-domain memory access is not allowed.
    Wednesday, July 15, 2009 5:43 PM
  • I still need help on this.

    Am I going about what I want the wrong way - should I use some other mechanism to ensure I don't read corrupted data?
    Thursday, July 23, 2009 9:07 PM
  • Nobody has come up with an idea, just don't do this.

    Hans Passant.
    Thursday, July 23, 2009 10:02 PM
    Moderator
  • > I need a way to synchronize access across app domains (and multiple user/terminal sessions) a la global mutex

    Does your application connect to a database?  If so, you might be able to conveniently turn this into a database problem.

    For example, Microsoft SQL Server has sp_getapplock and sp_releaseapplock where you can make your own named lock independent from any data actually in the database.  Unlike a global mutex, this will even work across machines as long as the apps connect to the same database.  Pass @LockMode='Shared' to get a read lock and @LockMode='Exclusive' to get a write lock.  You must use an SqlTransaction and you must hold the SqlTransaction and SqlConnection open from the time you call sp_getapplock until after sp_releaseapplock (which may or may not be simple to do depending on your application).

    If you are not using a database, this does give some insight into what you might be able to do: create a "service" (WCF, remoting, sockets, etc.) to manage locking.  You won't have the proper thread affinity, so I doubt that you'll be able to use ReaderWriterLock directly, but you should be able to implement an algorithm.  For example, I think you might be able to use the one on the Wikipedia page in conjunction with the System.Threading.Semaphore class.

    Another possibility is to just make the service actually contain all of the critical sections of code and let your application call into it whenever it must perform the operations protected by the lock.  If you do that, you should be able to use ReaderWriterLock in the service implementation directly.

    Whichever way you choose, be sure to test thoroughly. :)
    Thursday, July 23, 2009 10:49 PM