views:

162

answers:

2

I want to use Thread.VolatileWrite() (or an equivalent function) to change the value of a T[] field, so that the updated value is immediately visible to all other threads. However, the method does not provide a generic version, and I'm not able to use the Object overload since it takes a ref parameter.

Is there an alternative? Would Interlocked.Exchange<T> do the job? Is there a better way to achieve what I want to do?

+2  A: 

You can maybe use the volatile modifier. But check the documentation to see that the limitation don't apply to your case. And there is probably a performance penalty for using it.

Update: About using Interlocked. Notice that the documentation doesn't state that the changed value is visible to all threads. So it is probably not the same. But if you are in a situation that this is important. You must investigate further all the concurrency disaster possibilities.

Igal Serban
Thank you. I am already using the volatile modifier, and I was hoping I could avoid its penalty by calling VolatileWrite explicitly. (Please see my comment on Marc's answer.) Thanks.
Hosam Aly
+7  A: 

VolatileWrite is only useful if you also use VolatileRead; the volatile modifier is easier to use, but I wonder if it wouldn't be simpler to use synchronization - perhaps a ReaderWriterLockSlim (since it sounds like you have lots of readers).

Interlocked.Exchange<T> simply performs the get and set as an atomic operation; it doesn't (AFAIK) make any volatility claims (indeed, the compiler even tells you that a volatile field won't be treated as volatile when used as a ref argument).


Edit to clarify "it doesn't (AFAIK) make any volatility claims" - the behaviour of Interlocked is predictable, and you should see updates immediately on other thread as long as they also use Interlocked; my point is that if one thread uses Interlocked, and another relies on volatile (to talk to the same field), I don't know of any guarantees. Stick to one or the other for all access.

Marc Gravell
So you mean that, unless I use `VolatileRead` too, other threads may still have a cached value of the field?
Hosam Aly
Exactly. Hence the `volatile` modifier to make this simpler.
Marc Gravell
I was trying to use it in favor of using a volatile field, since that field is accessed very frequently, but only written to very, very few times (e.g. accessed 3n times, while written log(n) times only). So I thought I could introduce VolatileWrite only in write cases...
Hosam Aly
@Hosam: The problem is that unless the reading threads know to make sure they don't get a cached version, they could just not both looking at the newly published version. In fact, I believe that .NET (i.e. the MS CLI implementation) makes all writes volatile anyway - it's reads that need extra care.
Jon Skeet
Thank you Mark and Jon for your informative replies. :)
Hosam Aly