14

I am experiencing a bad behavior in my C# Multiple thread program. Some of my static members are loosing their values in other threads, while some statics of the same Declaring Type, do not loose their values.

public class Context {
  public Int32 ID { get; set; }
  public String Name { get; set; }

  public Context(Int32 NewID, String NewName){
      this.ID = NewID;
      this.Name = NewName;
  }
}

public class Root {
    public static Context MyContext;
    public static Processor MyProcessor;

   public Root(){
     Root.MyContext = new Context(1,"Hal");

     if(Root.MyContext.ID == null || Root.MyContext.ID != 1){
         throw new Exception("Its bogus!") // Never gets thrown
     }

     if(Root.MyContext.Name == null || Root.MyContext.Name != "Hal"){
         throw new Exception("It's VERY Bogus!"); // Never gets thrown
     } 

     Root.MyProcessor = new MyProcessor();
     Root.MyProcessor.Start();
   }
}

public class Processor {
   public Processor() {
   }

   public void Start(){
      Thread T= new Thread (()=> {

          if(Root.MyContext.Name == null || Root.MyContext.Name != "Hal"){
                throw new Exception("Ive lost my value!"); // Never gets Thrown
          }

          if(Root.MyContext.ID == null){
              throw new Exception("Ive lost my value!"); // Always gets thrown
          }

      });
   }
}

IS this a thread mutation problem while using static members of certain types?

6
  • 7
    As a rule, mutable static properties don't mix well with concurrency. You probably should be limiting the scope of that state, or ensuring it's not modified while being accessed concurrently. Commented Dec 18, 2012 at 19:25
  • Thanks for the reply, Properties or Field Members? I used Public Fields on purpose, in the Root Class. Commented Dec 18, 2012 at 19:26
  • 1
    My statement applies equally to properties and fields. They're both mutable public state, in some form. Commented Dec 18, 2012 at 19:28
  • Thanks for the general rule. There is much of the application not shown here for obvious reasons, I will keep the General rule in mind, but this does not solve my issue. Commented Dec 18, 2012 at 19:30
  • 1
    Are you seriously comparing int property to null and expect comparison to be true at some point? Commented Dec 18, 2012 at 19:37

3 Answers 3

14

Use volatile or alternatively access the variables using Interlocked.

The problem you run into is that the compiler (as well as the native compiler) is free to optimize access to the variables as he sees fit without them. So he may dump a variable into a register and just not reread it.

In order to avoid it, you must make sure that the variable is actually REALLY read. Volatile does that. Interlocked does that as well (and allows increment / add etc. to happen atomically).

Which is better you have to decide. Both force a memory barrier onto the processor which does have a non trivial cost when done often. One pattern I use regularly is to have those objects read only mostly, so that I only replace the root object (one memory barrier). Dealing with memory barriers manually (possible, read manual for the keyword) is a pain to get right. It is, though, a lot more efficient - depending how much you do there etc. it may be needed.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, this did help me. (RTFM was here for others, albahari.com/threading/part4.aspx ) correct link.
Grats. You just graduated advanced programming. Depending how complex the code is that can be terrible crappy to debug.
Thanks, the only thing I hate is dealing with this stuff in a high level lang ;P
+0: neither volatile no interlocked are good approaches for structure in the question: Context has 2 fields that are changed independently, so without proper lock one can easily get inconsisten set of values.
Read my comment. I would never update Context but make a new (read only) context, then replace the variable pointing to context. I use immutable objects a lot - lets everyone down the chain cache the data they access, often for historical reason (i.e. a new version may be in the pipeline but get processed later). Comment - I do financial trading apps mostly, pretty much all objects are immutable and get new versions generated.
3

Try using volatile modifier on variables which are modified/accessed from multiple threads

3 Comments

+0. 'volatile' may not help if value is modified from multiple threads. And deinitely will not help with "lost value" cases since it does not guarantee to read latest value or even consitent value of types that are bigger than int32/64.
"'volatile' may not help if value is modified from multiple threads": exactly that is what volatile does, ensure that this variable is really updated for every thread which is trying to access it.
(BTW all this volatile/interlocked is unrelated to OP problem :) ). Actually you are right - my coment is not entirely correct (Volatile gives you current value, but no way to make sure value did not change). OP case is different - class with 2 fields that are updated individually - there is nothing that can be marked volatile in this case that can provide consistent behavior.
2

Shared variables value in multi thread applications are non deterministic! you should use a lock on each of your shared resources to avoid collision in your logic:

    static Readonly Object _lock=new Object();
    lock(_lock)
    {
    //accessing your shared variable
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.