Setheron
Setheron

Reputation: 3740

C#: Question regarding thread safety for member variables

Can someone explain why examples on threading will always make an object (specifically a member variable) static if it is to be accessed by multiple threads?

My issue is that making the member variable static means that it will be shared among all other instantiations of the class. Sometimes I find that I would like multiple threads within a class "touch" the member variable but at the same time allow every object to have their own copy.

Would the answer to performing what I mentioned simply be replacing:

Upvotes: 2

Views: 2026

Answers (2)

Ruben
Ruben

Reputation: 15515

If you want each thread to use the same member variable, but also maintain a separate copy, you've got a contradiction here. Either they use the same variable or they don't. Unless I'm not understanding you right.

Having said that, if you really need a static field to be accessed by multiple threads, each maintaining their own, private value, you can use the ThreadStatic attribute. This attribute ensures that the static field will be private to each thread ("thread local" as it's usually called).

[ThreadStatic]
private static bool s_threadHasDoneItsWork;

Note that you cannot initialize a thread local static field through a static constructor or directly as static type field = value. (The compiler won't complain, but it won't work properly.)


volatile tells the runtime that the field (static or not) must always be accessed directly from your main memory, so you don't need to use locks or memory barriers to synchronize threads and cores. It's always up-to-date, so to speak, whereas other fields can still be waiting for your processor's memory cache to sync up with your main memory.

But that's exactly the limit of what it does: only access to that particular field. As soon as you've read it, the value is stale again, so don't ever think of doing something like volatileField++ (which means "read volatileField, add one to the value you've just read, set volatileField", and not "increment volatileField", you'll need to use the Interlocked class for that, which is a lot more expensive).

A safe way to use volatile fields is reading them directly, but when you're modifying them, to use a locking mechanism before you either read or write them. (The only reasonable exception I can think of is a boolean flag like "I'm done now".)

The practical use of volatile fields is, not surprisingly, rather limited. Stick with simple locking; the lock keyword, and the corresponding Monitor class's methods take care of both the single user and memory synchronization (as soon as you enter and exit the lock).

Upvotes: 3

Reed Copsey
Reed Copsey

Reputation: 564413

There is nothing that requires member variables to be static for threading.

Most examples use a static variable, specifically because they're trying to show how to synchronize data between two separate threads. If you wish to do this, you need to have a value that's accessible by both threads. Static variables are the simplest option, since they're accessible everywhere.

You could just as easily pass a reference to a class into your thread, and have that thread and your main thread share a non-static member variable. You will need to provide a good locking/synchronization mechanism, however, since you'll have two threads sharing one instance of a class.

Upvotes: 8

Related Questions