I'm building a multi threaded cache in C#, which will hold a list of Car objects:
public static IList<Car> Cars {get; private set;}
I'm wondering if it's safe to change the reference in a thread without locking ?
e.g.
private static void Loop() { while (true) { Cars = GetFreshListFromServer(); Thread.Sleep(SomeInterval); } }
Basically it comes down to whether assigning a new reference to Cars is atomic or not I'd guess.
If it's not I'll obviously have to use a private field for my cars, and lock around getting and settings.
Reference assignment is atomic. Interlocked. Exchange does not do only reference assignment. It does a read of the current value of a variable, stashes away the old value, and assigns the new value to the variable, all as an atomic operation.
Yes, reference updates are guaranteed to be atomic in the language spec.
Thread SafetyStatic variables are not thread safe. Instance variables do not require thread synchronization unless shared among threads. But, static variables are always shared by all the threads in the process. Hence, access to static variable is not thread safe.
This can be a little bit confusing, but as it turns out, the static properties on a static class are not thread safe. What this means is that the property is shared between threads.
Yes, reference updates are guaranteed to be atomic in the language spec.
5.5 Atomicity of variable references
Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types. In addition, reads and writes of enum types with an underlying type in the previous list are also atomic. Reads and writes of other types, including long, ulong, double, and decimal, as well as user-defined types, are not guaranteed to be atomic.
However inside a tight loop you might get bitten by register caching. Unlikely in this case unless your method-call is inlined (which might happen). Personally I'd add the lock
to make it simple and predictable, but volatile
can help here too. And note that full thread-safety is more than just atomicity.
In the case of a cache, I'd be looking at Interlocked.CompareExchange
, personally - i.e. try to update, but if it fails redo the work from scratch (starting from the new value) and try again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With