views:

556

answers:

3

I have a reference-type variable that is readonly, because the reference never change, only its properties. When I tried to add the volatile modifier to it the compiled warned me that it wouldn't let both modifiers apply to the same variable. But I think I need it to be volatile because I don't want to have caching problems when reading its properties. Am I missing anything? Or is the compiler wrong?

Update As Martin stated in one of the comments below: Both readonly and volatile modifiers apply only to the reference, and not to the object's properties, in the case of reference-type objects. That is what I was missing, so the compiler is right.

class C
{
    readonly volatile string s;  // error CS0678: 'C.s': a field cannot be both volatile and readonly
}
+1  A: 

A readonly field can only be written when the object is first constructed. Therefore there won't be any caching issue on the CPU because the field is immutable and can't possibly change.

NathanE
I understand your logic, but I disagree. An object can be readonly and still changes through its properties, because its properties aren't readonly. The readonly property in this case only prevents from assigning the variable to another object. At least is that what I understood from what I learned.
Jader Dias
@Vernict: The readonly and volatile modifiers only protect the reference (or the value in case of atomic values like bool, int), not the content of the object! That's a completly different matter.
Martin C.
A: 

While the reference itself might be thread-safe, its properties might not. Think about what would happen if two threads tried to simultaneously iterate through a List contained within your reference object.

Charlie Salts
But that's something neither read-only nor volatile are intended to protect against. That's something you need to solve with synchronization anyways.
Martin C.
@Charlie, you are saying that even if the object is volatile, it doesn't guarantee that its properties will be volatile?
Jader Dias
@Martin C, very true.@Vernicht, As I understand, yes. You'll need to guarantee that your fields and properties are thread-safe.
Charlie Salts
+8  A: 

Neither the readonly nor volatile modifiers are penetrative. They apply to the reference itself, not the object's properties.

The readonly keyword asserts—and enforces—that a variable cannot change after initialization. The variable is the small chunk of memory where the reference is stored.

The volatile keyword tells the compiler that the contents of a variable might be changed by multiple threads. This prevents the compiler from using optimizations (such as reading the variable's value into a register and using that value over several instructions) that might cause problems with concurrent access. Again, this only affects the small chunk of memory where the reference is stored.

Applied this way, you can see that they are indeed mutually exclusive. If something is readonly (can only be written to once, at initialization or construction), then it can't also be volatile (can be written to at any time by multiple threads).


As for your concern about caching issues, IIRC, there are pretty strict rules about when the compiler can cache the result of a property call. Keep in mind that it is a method call, and it's a pretty heavy optimization (from the compiler's stand-point) to cache its value and skip calling it again. I don't think it's something you need to concern yourself with overly much.

P Daddy
The properties may be uncacheable (I wouldn't know), but the backing fields definitely are. The fields should be marked volatile.
configurator