views:

110

answers:

2

I have some legacy code that uses Interlocked.Equals to compare values. The values may be two bools or it may compare an array of structs to null. Resharper complains about Interlocked.Equals saying "access to a static member of a type via a derived type". I know that Equals is not a member of the Interlocked class, but rather is a member of the object class. The comparison is happening in a thread so I assume the original coder wanted to do the comparison as an atomic operation hence the use of Interlocked. Since object.Equals is not atomic what is the proper, thread safe, way to do these kinds of comparisons? Note, most of the data is static, some of it is static volatile.

+3  A: 

Single reads of booleans or object references are atomic. So, if you're comparing one shared value to a constant or local variable, no "interlocking" is necessary. As Jon stated, you would need to use Interlocked.CompareExchange to ensure you're reading the latest value written, unless the shared variables are volatile.

If both comparands are shared, then you'll need an actual lock. There isn't a way to atomically compare two shared values AFAIK.

Update:

I do recommend the introduction of explicit locks for shared data. Keep in mind that the original code was completely broken, so don't be shy about changing it.

If you think about it, what would you do with the result of the comparison? It doesn't really make sense; as soon as you have the result, it could be wrong. A lock would need to be held longer than just for the comparision for the comparision to be useful for anything.

Stephen Cleary
Atomic != volatile. You could end up reading stale data.
Jon Skeet
Yes, some of the values are shared. I will add that detail to my questions.
Bill W
@Jon: You are correct. My answer's been updated.
Stephen Cleary
+3  A: 

You can't make the whole comparison atomic, but it's not really atomicity you're interested in. It's volatility, I suspect. That's what ensures that when you read a value, you definitely get the latest version, rather than seeing a value which was valid at some point in the past, but may not be. If you really need atomicity across the read/read/compare part, I suspect you're going to need locking.

You could use Interlocked.CompareExchange to make sure you're reading the most recent value.

Do you absolutely have to use lock-free threading in the first place? I would strongly suggest either building on top of bigger structures (e.g. Parallel Extensions) or just using locks for shared data (which should be avoided where possible anyway).

Jon Skeet
That should have been "array of structs". Sorry, bad editing on my part. I have corrected it in my question.
Bill W
@Bill W: Okay, removed.
Jon Skeet