Volatile for reference type in .net 4.0

I got confused in volatile for reference type.

I understand that for a primitive type, volatile can immediately reflect changes in values ​​from another thread. For a reference type, it can immediately reflect address changes. However, what about the contents of the object. Are they still cached?

(Assuming List.Add() is an atomic operation)

For example, I have:

 class A { volatile List<String> list; void AddValue() { list.Add("a value"); } } 

If one thread calls the AddValue function, the address of the list does not change, will the other thread be updated to change the contents of the list, or can the contents be cached for each thread, and this is not an update for other threads?

+8
c # volatile
source share
4 answers

I understand that for a primitive type, volatile can immediately reflect changes in values ​​from another thread

You misunderstand in at least three ways. You should not try to use volatile until you understand all about weak memory models, get and release semantics, and how they affect your program.

First of all, make sure volatile affects variables , not values .

Secondly, volatile does not affect variables that contain values ​​of value types in a different way than variables that contain references.

Thirdly, volatile does not mean that a change in value from other threads is immediately visible. . Volatile means that variables acquire and release semantics. Volatile affects the order in which side effects of memory mutations from a specific thread may occur. The idea that there is a consistent universal order of mutations and that these mutations in this order can be instantly observed from all threads is not a guarantee of a memory model.

However, what about the contents of the object?

How about this? The storage location referenced by a variable of a reference type does not need any specific thread characteristics.

If one thread calls the AddValue function, the address of the list does not change whether the other thread will be updated to change the contents of the list.

Nope. Why? This other thread may be on a different processor, and a page containing the address of the array that supports the list may be preloaded in this processor cache. Mutating the list may have changed the location of the store, which contains the address of the array, to link to a completely different location.

Of course, the list class is not thread safe in the first place. If you do not block access to the list, then the list may simply crash and die when you try to do this.

You do not need volatility; you need to set thread locks around access to the list. Since ceiling locks cause full fences, you don't need half fences introduced by volatile ones.

+19
source share

This is worse than that.

If you access an object that is not thread safe at the same time, your program may really crash. Obtaining outdated information is not the worst potential result.

When sharing the base class .NET library objects between threads, you really have no choice but to use locking. For contactless programming, you need invasive changes to your data structures at the lowest levels.

+6
source share

The volatile keyword does not affect the contents of the list (or, more precisely, the object referenced).

Speaking of updated / not updated for another thread, this is a simplification of what happens. You must use the lock statement to synchronize access to the shared list. Otherwise, you are effectively faced with the conditions of the race, which can lead to the failure of the program. The List<T> class itself is not thread safe.

+2
source share

See http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword for a good explanation of what volatility is and how it affects fields.

All the streams on this site must be read, it contains a huge amount of useful information, which turned out to be very useful for me when I was developing multithreaded software.

+1
source share

All Articles