我有一个类似下面的课程:
class Program
{
static void Main(string[] args)
{
var outputWindow = new OutputWindow();
var threads = new List<Thread>();
Action action = () => outputWindow.Display(20);
for (int i = 0; i < 10; i++)
{
var thread = new Thread(() => action()) {Name = "Thread " + i};
threads.Add(thread);
}
foreach (var thread in threads)
{
thread.Start();
}
}
}
public class OutputWindow
{
public void Display(int x)
{
for (int i = 0; i < x; i++)
{
Console.WriteLine(Thread.CurrentThread.Name + " Outputcounter: " + i);
}
}
}
问题是 - 这个线程是否安全,这会导致显示方法中局部变量i的任何竞争条件?是否所有线程都会按预期增加变量“i”的值(这是增加值并且不会嵌入到i的其他线程值中)
如果这是线程安全的,那么可以安全地假设在方法中声明的任何局部变量总是线程安全的并且共享变量是需要同步的变量吗?
谢谢, -Mike
答案 0 :(得分:13)
每个方法调用都有一组单独的局部变量。但是,这些变量可以引用其他方法也使用的对象。例如:
public void AppendSomething(StringBuilder builder)
{
builder.Append("Something");
}
这里builder
仍然是局部变量(参数是局部变量),AppendSomething
的每个调用都有一个独立的变量 - 但你可以从多个调用方法线程使用相同的StringBuilder
引用,因此该方法不线程安全。 (因为StringBuilder
不是线程安全的。)
答案 1 :(得分:3)
只要您的数据是本地数据,是的,它就是线程安全的。如果它引用该方法之外的数据,那么它就不是。
在您的示例中,i
不受多个线程的影响(因为您创建变量,设置本地值并仅增加值)。
如果我引用了方法之外的东西(例如文件),那么它就不是线程安全的,因为你可能在不同的线程上引用相同的文件。
答案 2 :(得分:1)
局部变量在方法中是线程安全的,只要您不将它们传递给其他线程即可。如果你这样做,则取决于。
例如,在您的代码中,您创建的所有主题都具有对outputWindow
和threads
的共享访问权限。如果对象不是线程安全的,并且您从多个线程调用它们,那么您可能会遇到问题。例如,如果每个线程在完成时尝试将其自身从threads
中删除,那么您就会遇到问题,因为List<>
对于读/写来说不是线程安全的。
您的所有主题都使用相同的OutputWindow
实例。如果对Display
的调用改变了对象的状态,那么需要确保变异是线程安全的,否则你就会遇到竞争条件。