2

I've got a static variable (abstract data type, not a primitive) in my C# ASP.NET project.

It will be read by many threads, concurrently and frequently.

I need to write to it very rarely (compared to number of reads).

What is the best way of ensuring threadsaftey so that whilst im writing to it, other threads aren't reading partially-written data?

I've only ever used lock, but i understand this will prevent concurrent reads :(

Thanks

Andrew Bullock
  • 36,616
  • 34
  • 155
  • 231

3 Answers3

6

I'd start off just with lock. Uncontested locks are very cheap. You could use ReaderWriterLockSlim (assuming you're using .NET 3.5) but a lock is simpler to get right. Optimise it if/when it becomes a problem.

Straight ReaderWriterLock may well be slower than the simple lock - it's not as fast as it might be, hence the slim version :)

Just how frequently do you mean by "frequently"? How much contention do you expect? You might want to model it (e.g. simulate a reasonable number of requests) and benchmark no locking vs simple locking, just to see what the overhead is.

You may be able to use the lock-free option of volatile - but frankly I've recently given up on that as too hard for sane people to reason about. (It doesn't mean what I thought it meant.)

What are you actually doing with the data? Is the type an immutable type, so once you've got the right reference, you can read in a thread-safe way without any locking?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Good advice- that is one of oddities in the .NET framework that unless you read about it you might end up making the wrong choice. – RichardOD Sep 04 '09 at 10:54
  • @Andrew- here's a good article if you want to read more about it- http://blogs.msdn.com/pedram/archive/2007/10/07/a-performance-comparison-of-readerwriterlockslim-with-readerwriterlock.aspx – RichardOD Sep 04 '09 at 10:57
  • thanks for the advice. I'll be reading on every request, so as frequently as there is traffic. writing will in the order of once a day. – Andrew Bullock Sep 04 '09 at 11:10
  • i think ive overlooked the immutability aspect. at the moment its not (but could be) so locking doesnt really help me. Hmm, time for a rethink. If i made it immutable perhaps i wouldn't need any locking as requests can just take a copy – Andrew Bullock Sep 04 '09 at 11:15
  • @Andrew: You'd still need to either lock or make it volatile, to avoid getting stale data. – Jon Skeet Sep 04 '09 at 12:54
  • yeah i realise that, last comment didnt end up saying what i meant. I've posted my solution below – Andrew Bullock Sep 04 '09 at 13:42
1

You can use the ReaderWriterLock, which is more difficult to use than lock, but it allows concurrent reads: http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx

chris166
  • 4,769
  • 4
  • 24
  • 25
0

Thanks for your help people, I've settled on this approach until performance becomes an issue. Presumably this is correct (threadsafe), where SharedResource is immutable

public static class SharedResourceManager
{
    private static readonly object syncLock = new object();

    private static SharedResource res { get; set; }

    public static SharedResource Resource
    {
        get
        {
            lock (syncLock)
                return res;
        }
        set
        {
            lock(syncLock)
                res = value;
        }
    }
}
Andrew Bullock
  • 36,616
  • 34
  • 155
  • 231
  • Yes, that's safe. Using a volatile private variable would probably be okay too. Any reason you're using a property at all for `res`, given that it's private? – Jon Skeet Sep 04 '09 at 14:03