是线程之间共享的一个方法的局部变量
本文关键字:一个 方法 局部变量 线程 之间 共享 | 更新日期: 2023-09-27 17:57:56
我有这样一个类的实例:
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();
}
}
在我的程序中,我实例化了几个新线程。每个线程都运行上面类中的"Run()"方法。
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();
}
我希望看到一个从0到9的数字列表,但没有按顺序排列。但我的结果显示,"Run()"方法中的"ID"变量作为局部变量在所有线程之间共享。
![Output][1]
我想知道我是否有一个类的实例,并且许多线程从该实例运行一个方法,那么该方法的局部变量是否在所有线程之间共享?或者每个线程都有自己的本地副本?我应该为该类中的每个线程创建一个新实例吗?
否,线程之间不共享局部变量。在这方面,您的参数ID
是一个局部变量。它不是共享的。
您所看到的是由一个称为捕获循环var的标准问题引起的。使用额外的变量很容易解决
for (int j = 0; j < 10; j++)
{
int copy = j;
Thread T = new Thread(delegate() { O.Run(copy); });
T.Start();
}
我希望这能说明问题所在:j
变量是由您的匿名方法捕获的,实际上这意味着它被O.Run()
的所有调用站点共享(通过引用)。
否,局部变量不在线程之间共享。如果您正在调试线程,请确保打开线程窗口,这样,如果您想监视变量,就可以在线程之间切换。否则,如果手表卡在一根线上,你可能会得到误导性的结果。
我在你的程序运行一次时得到了以下输出,尽管由于它的性质,你每次都会得到不同的结果。
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
试试这个:
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();
}
}
否,线程之间既不共享局部变量,也不共享方法参数。您所看到的是因为变量j
在您正在创建的匿名委托之间共享。因此,在您的情况下,有一个全局j
,每个线程的Run()
都会在调用方法时获得变量的值,这可能是在j
为下一次迭代递增之后。
你可以通过创建一个新的变量来解决这个问题,这个变量是每个迭代的"本地"变量:
for (int j = 0; j < 10; j++)
{
int tmp = j;
Thread T = new Thread(delegate() { O.Run(tmp); });
T.Start();
}