9

After reading Jon Skeet article , and this article from msdn , I still have a question

Let's say I have this code :

  MyPerson mp = new MyPerson(); //Field

  int g=0; //Field

  public void DoWork ()
   {
      int i;
      MyPerson mp2 = new MyPerson();  
      ...
   }

Now let's say I have 2 threads. which runs DoWork. ( let's ignore for now , race conditions)

  • Will they both see the same g or each thread will have its own item ? ? ( value )

  • Will they both see the same mp or each thread will have its own item ?? ( instance )

  • Will they both see the same i or each thread will have its own item ? ( value )

  • Will they both see the same mp2 or each thread will have its own item ? ( instance )

  • if they both see the same , why would I need static ?

I've searched a lot about this topic , and couldn't find any article which states : Different Threads ,ref types and value types... )

Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • How is the class created by the calling thread code? – asawyer Dec 03 '12 at 10:34
  • @asawyer just run in main 3 times `ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork ),null);` – Royi Namir Dec 03 '12 at 10:37
  • 1
    @RoyiNamir in the line above, the target instance is `this` each time - it is actually `new WaitCallback(this.DoWork)`. So if your code does that 3 times, then yes: they are 3 delegates targeting the same instance, so `mp` and `g` are shared **but** note what I was saying about changes not necessarily being observed unless you use a memory barrier (synchronization) or `volatile` access. For really complex reasons. – Marc Gravell Dec 03 '12 at 10:46
  • @MarcGravell but `writing` is not requires memory-barrier/lock/volatile. right ? only reading...? – Royi Namir Dec 03 '12 at 10:50
  • 1
    @RoyiNamir depends on a lot of factors; for example, while yes: all writes are implemented as volatile writes, that is an implementation detail that shouldn't be used (when doing thread semantics, you care about what is **guaranteed**, and that: isn't). Also, it depends on the data size: `int`, `float`, etc, plus references are guaranteed to be atomic writes; but large structs (including `double` and `long`) are **not** guaranteed to be atomic writes. For primitives, `Interlocked` is handy for that; but otherwise: you'll definitely need synchronization to avoid torn values. – Marc Gravell Dec 03 '12 at 10:54

2 Answers2

13

Neither thread simply "runs DoWork"; they run DoWork on a particular object. If the two threads are created targeting different instances, then mp and g will be completely separate fields. If the two threads are created targeting the same instance, then mp and g will be shared but it is not guaranteed that the threads will see changes made by the other thread unless you use synchronization or volatile access.

For example:

var obj = new SomeObject();
Thread thread1 = new Thread(obj.DoWork);
Thread thread2 = new Thread(obj.DoWork); // clearly targeting the same instance

vs

var obj = new SomeObject();
Thread thread1 = new Thread(obj.DoWork);
obj = new SomeObject();
Thread thread2 = new Thread(obj.DoWork); // targeting a different instance

The local variables i and mp2 are strictly specific to each thread.

Additional note: even if they are separate fields/locals, if some of the code in the ... later reassigns mp or mp2 to refer to the same object, then they will be squabbling over the same object; the same synchronization / volatile rules will apply.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Marc , Can you please explain _If the two threads are created targeting different instances_ ? – Royi Namir Dec 03 '12 at 10:39
  • Basically, and in fact how it works internally, is the instance of the object is passed to the `DoWork` method as "`this`". A nice way of visualising it I think. (Under the hood, all instance methods on a class have a first parameter for '`this`') – Kieren Johnstone Dec 03 '12 at 10:44
  • @MarcGravell What if there is another method called `DoWork2()` which creates 2 threads which runs `DoWork()` . is it as the same as targeting the same instance explanation? – Royi Namir Feb 01 '13 at 18:17
3

The variables g and mp are 'global' to the containing class, so these will be the same objects seen by both threads. i is a local variable that is declared in the DoWork event; subsequently this will only be 'visible' to the background/alternative thread.

They don't 'see' the same, so the static keyword in this case has no relevence.

I hope this helps.

MoonKnight
  • 23,214
  • 40
  • 145
  • 277