1

When you want to use a ReaderWriterLock you declare it like this:

ReaderWriterLock rwLock = new ReaderWriterLock;

Well if you are doing that for all your different threads that are going to access some resource that you want to protect, they (presumably) are all using differnt ReaderWriterLock instances.

How is the ReaderWriterLock instance shared amongs threads?

Also, as a bonus, can someone confirm for me that what you are really "locking" is the ReaderWriterLock state, not any resource. Unlike lock(someResourceToLock), you aren't locking anything but the ReaderWriterLock instance's state (whether it is in read or write mode, and whether you are allowed to read and write yet).

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
richard
  • 12,263
  • 23
  • 95
  • 151

2 Answers2

2

If you are using the ReaderWriterLock rwLock = new ReaderWriterLock per thread or per method (i.e. as a method variable), then your code is most-likely broken. It is not a singleton; it relies on all threads accessing the protected data using the same lock. This is most commonly achieved by placing the lock in a field, i.e.

class Foo {
    ReaderWriterLock rwLock = new ReaderWriterLock();
    // lots of code accessing the rwLock field for this instance
}

Also - maybe consider ReaderWriterLockSlim in many scenarios; less overhead. Re your follow-up; when acquiring the lock you are changing the internal state (in a thread-safe manner) to preserve the "many-readers nand single-writer" expectation (perhaps blocking until that is possible, i.e. conflicting locks have been withdrawn).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Thanks. The examples in my book are pretty poor then. . . So if you place the lock in a field, would you want it to be static, so that every thread that accesses the class would be using the same lock? – richard Apr 20 '11 at 06:56
  • @Richard - static and threads are orthogonal; usually you want every thread that accesses the same **instance** of the class to use the same lock, so it would be an instance (i.e. non-static) field. If you are trying to protect `static` state, then a `static` lock is desirable - but try to avoid using too much `static` state - it is usually a bad sign. – Marc Gravell Apr 20 '11 at 06:58
  • Ok, I see, except I am not sure what you mean by orthogonal (the only part of what you said that I don't understand). – richard Apr 20 '11 at 07:02
  • @Richard [orthogonal](http://en.wikipedia.org/wiki/Orthogonality#Computer_science) i.e. mostly unrelated. Actually, that's not *quite* true, as there is a common expectation that static data should be thread-safe, but since we should be avoiding too much static data *anyway* that is usually moot – Marc Gravell Apr 20 '11 at 07:08
  • Thank you, as always I appreciate you taking the time to answer my questions. – richard Apr 20 '11 at 07:17
2

How is the ReaderWriterLock instance shared amongs threads?

Create a single instance of ReaderWriterLock and use it from all threads that are accessing the shared resource you want to protect.

Also, as a bonus, can someone confirm for me that what you are really "locking" is the ReaderWriterLock state, not any resource. Unlike lock(someResourceToLock), you aren't locking anything but the ReaderWriterLock instance's state

You really are locking.

lock(obj) { ... } is just a short cut for (simplified here, the real implementation has some additional subtleties to handle edge cases):

Monitor.Enter(obj)
  ...
try {
} finally {
  Monitor.Exit(obj);
}

using the field in every reference type to hold the state used by Monitor.


As Marc notes, consider ReaderWriterLockSlim unless you need the fairness (threads guaranteed to enter in the order they starting waiting) that ReaderWriterLock gives.

Richard
  • 106,783
  • 21
  • 203
  • 265
  • What I asking for confirmation on was that ReaderWriterLock doesn't lock any _resource_, it is locking itself, essentially. Is that correct? – richard Apr 20 '11 at 07:09
  • `Monitor.Enter` / `Monitor.Exit`, no? Note that the implementation changes between C# and .NET versions too (i.e. C# 4 will try to use a different API if available, falling back to the one indicated otherwise) – Marc Gravell Apr 20 '11 at 07:11
  • @RichardDesLonde: Both ways of stating it work in English, but that's a limitation of English :-). I would normally talk about using the `ReaderWriterLock` instance to lock the resource because the resource is the important thing. However you are right in that the `ReaderWriterLock` doesn't itself have any information or state representing what you are using it to protect. – Richard Apr 20 '11 at 07:12
  • @Marc: clearly I do need that coffee :-(. The use of the lockTaken boolean is what I was avoiding with the parenthetical comment. – Richard Apr 20 '11 at 07:13