Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What to use instead of Interlocked.Equals

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.

like image 687
Bill W Avatar asked Jul 20 '10 14:07

Bill W


People also ask

What is interlocked exchange?

Interlock. Exchange returns the original value while performing an atomic operation. The whole point is to provide a locking mechanism. So it is actually two operations: read original value and set new value.

What is Interlocked in c#?

It lets you do small and well-defined operations safely in a multi-threaded environment: for instance, if you want two threads to increment the same variable, you can use Interlocked to do it instead of acquiring a heavyweight lock and using the "regular increment".

Is interlocked increment thread safe?

Interlocked provides some methods to handle incrementing, decrementing, adding 64-bit values (which also isn't threadsafe), and so on. On a similar run of 100,000 items, this method is safe where the first one was not.


2 Answers

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).

like image 184
Jon Skeet Avatar answered Oct 13 '22 22:10

Jon Skeet


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.

like image 23
Stephen Cleary Avatar answered Oct 13 '22 21:10

Stephen Cleary