开发者

Are the local variables of one method shared between threads?

I have instance from a class like this:

public class One
{
    Semaphore S = null;
    public One(Semaphore S)
    {
        this.S = S;
    }
    public void Run(int ID)
    {
        S.WaitOne();
        Console.WriteLine("Thread [" + ID + "] Entered");
        Random R = new Random();
        Thread.Sleep(R.Next(100, 1000));
        Console.WriteLine("Thread [" + ID + "] Exited");
        S.Release();
    }
}

In my program I instantiate several new threads. Each thread runs the "Run()" method in开发者_JS百科 the above class.

Semaphore S = new Semaphore(5, 5);
One O = new One(S);
for (int j = 0; j < 10; j++)
{
     Thread T = new Thread(delegate() { O.Run(j); });
     T.Start();
}

I expected to see a list of numbers from 0 to 9 but in non-sorted order. but my result shows that the "ID" variable in "Run()" method as a local variable is shared between all threads.

 ![Output][1]

I want to know if I have one instance of a class and many threads run a method from that instance, so are the local variables of that method shared between all threads? or each thread has its own local copy? Should I create a new instance for each thread from that class?


No, local variables are not shared between threads. And your paramter ID is a local var in this respect. It is not shared.

What you see is caused by a standard problem called the captured loop var. It is simple to solve with an extra variable:

for (int j = 0; j < 10; j++)
{
     int copy = j;
     Thread T = new Thread(delegate() { O.Run(copy); });
     T.Start();
}

And I hope this shows where the problem is: the j variable is captured by your anonymous method, in effect this means it is shared (by reference) by all the call-sites of O.Run().


No, locals are not shared between threads. If you are debugging threads be sure to open the threads window so you can switch between threads if you want to watch a variable. Otherwise you may get misleading results if the watch is stuck on one thread.

I get the following output on one run of your program, although due to it's nature you can get different results each time.

Thread [1] Entered
Thread [2] Entered
Thread [4] Entered
Thread [4] Entered
Thread [5] Entered
Thread [2] Exited
Thread [1] Exited
Thread [10] Entered
Thread [6] Entered
Thread [6] Exited
Thread [10] Exited
Thread [9] Entered
Thread [8] Entered
Thread [4] Exited
Thread [5] Exited
Thread [8] Entered
Thread [4] Exited
Thread [8] Exited
Thread [9] Exited
Thread [8] Exited


try this:

static void Main(string[] args)
{
    Semaphore S = new Semaphore(5, 5);
    One O = new One(S);
    for (int j = 0; j < 10; j++)
    {
        Thread T = new Thread(new ParameterizedThreadStart(O.Run));
        T.Start(j);
    }
}

public class One
{
    Semaphore S = null;
    public One(Semaphore S)
    {
        this.S = S;
    }
    public void Run(object ID)
    {
        // int id = (int) ID;  // when you need an int
        S.WaitOne();
        Console.WriteLine("Thread [" + ID + "] Entered");
        Random R = new Random();
        Thread.Sleep(R.Next(100, 1000));
        Console.WriteLine("Thread [" + ID + "] Exited");
        S.Release();
    }
}


No, neither local variables, nor method parameters are shared between threads. What you are seeing is because the variable j is shared between the anonymous delegates you are creating. So, in your case, there is one global j and every thread's Run() gets the value the variable has when the method is called, which may be after the j is incremented for the next iteration.

You can fix this by creating a new variable, that is “local” to each iteration:

for (int j = 0; j < 10; j++)
{
     int tmp = j;
     Thread T = new Thread(delegate() { O.Run(tmp); });
     T.Start();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜