phi*_*131 14 c# multithreading local-variables
我真的找不到关于这个确切主题的任何内容,所以如果问题已经存在,请引导我走向正确的方向.
根据我对.NET的了解,不可能跨不同的线程访问变量(如果该语句错误,请纠正我,这正是我在某处读到的).
然而,现在在这个代码示例中,它似乎不应该工作:
class MyClass
{
public int variable;
internal MyClass()
{
Thread thread = new Thread(new ThreadStart(DoSomething));
thread.IsBackground = true;
thread.Start();
}
public void DoSomething()
{
variable = 0;
for (int i = 0; i < 10; i++)
variable++;
MessageBox.Show(variable.ToString());
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void SomeMethod();
{
MyClass mc = new MyClass();
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行时SomeMethod()不应该.NET抛出异常,因为创建的对象mc运行在与mc-initializer中创建的线程不同的线程中,并且这个新线程正试图访问本地变量mc?
这些MessageBox节目10是(不)预期的,但我不确定为什么这应该有效.
也许我不知道要搜索什么,但我找不到任何线程主题,会解决这个问题,但也许我对变量和线程的想法是错误的.
Eri*_*ert 47
根据我对.NET的了解,不可能跨不同的线程访问变量.如果该陈述是错误的,请纠正我,这正是我在某处读到的.
这句话完全是假的,所以请考虑一下你的修正.
您可能在某处读过不能在不同线程上访问局部变量的地方.该陈述也是错误的,但通常是陈述.正确的说法是那些不是的局部变量
yield return或的方法yield break)多个线程无法访问.甚至那个说法有点狡猾; 有方法可以用指针和unsafe代码块来做到这一点,但尝试这样做是一个非常糟糕的主意.
我还注意到你的问题询问了局部变量,但后来给出了一个字段的例子.根据定义,字段不是局部变量.根据定义,局部变量是方法体的本地变量.(或构造函数体,索引器主体等)确保您清楚.本地的定义特征不是它"在堆栈中"或某种类似的东西; 本地的"本地"部分是它的名称在方法体外没有意义.
在一般情况下:变量是指存储器的存储位置.线程是进程中的控制点,进程中的所有线程共享相同的内存; 这就是使他们成为线程而不是进程的原因.因此,通常情况下,所有变量都可以由多个线程在所有时间和所有顺序中访问,除非采用某种机制来防止这种情况发生.
让我再说一遍,只是为了确保它在你的脑海中绝对清晰:考虑单线程程序的正确方法是所有变量都是稳定的,除非有些东西使它们发生变化.考虑多线程程序的正确方法是所有变量都在不按特定顺序进行变异,除非某些变量保持静止或有序. 这是多线程共享内存模型如此困难的根本原因,也就是为什么要避免它.
在您的特定示例中,两个线程都可以访问this,因此两个线程都可以看到该变量this.variable.您没有实现任何机制来阻止这种情况,因此两个线程都可以按任何顺序写入和读取该变量,但实际上受到的限制非常少.您可以实现以驯服此行为的一些机制是:
ThreadStatic.这样做会导致在每个线程上创建一个新变量.volatile.这样做会对可能观察到的读取和写入顺序施加某些限制,并且还会对编译器或CPU可能导致意外结果的优化施加某些限制.lock语句围绕变量的每次使用.除非您对多线程和处理器优化有深入的了解,否则我建议除了后者之外的任何选项.
现在,假设您确实希望确保在另一个线程上对变量的访问失败.您可以让构造函数捕获创建线程的线程ID并将其存储起来.然后,您可以通过属性getter/setter访问该变量,其中getter和setter检查当前线程ID,如果它与原始线程ID不同,则抛出异常.
基本上它的作用是滚动你自己的单线程公寓线程模型."单线程单元"对象是一个只能在创建它的线程上合法访问的对象.(你买一台电视,你把它放在你的公寓里,只允许你公寓里的人看你的电视.)单线程公寓与多线程公寓和免费线程的细节相当复杂; 有关更多背景,请参阅此问题.
这就是为什么,例如,您必须永远不能从工作线程访问您在UI线程上创建的UI元素; UI元素是STA对象.
根据我对.NET的了解,不可能跨不同的线程访问变量(如果该语句错误,请纠正我,这正是我在某处读到的).
这是不正确的.可以从范围内的任何位置访问变量.
从多个线程访问相同的变量时需要谨慎,因为每个线程可以在非确定性时间对变量进行操作,从而导致细微的,难以解决的错误.
有一个出色的网站,涵盖从基础到高级概念的.NET中的线程.
http://www.albahari.com/threading/
我有点晚了,@ Eric J.给出的答案非常精彩而且非常重要.
我只想在你对线程和变量的看法中为另一个问题添加一些清晰度.
你在你的问题的标题"在另一个线程中访问变量"中说过这个.除此之外,在您的代码中,您正在从1个线程访问您的变量,这是在此处创建的线程:
Thread thread = new Thread(new ThreadStart(DoSomething));
thread.IsBackground = true;
thread.Start();
Run Code Online (Sandbox Code Playgroud)
所有这些事情让我意识到你害怕与实际创建实例的线程不同的线程MyClass将使用来自该实例内部的东西.
以下事实对于更清晰地了解多线程是什么非常重要(它比您想象的更简单):
编辑
我看到线程安全这个词出现在这个答案的主题上.万一你可能想知道这些词是什么意思我推荐这篇由@Eric Lippert撰写的精彩文章:http: //blogs.msdn.com/b/ericlippert/archive/2009/10/19/what-is-this-thing -你的呼叫线程safe.aspx
| 归档时间: |
|
| 查看次数: |
23500 次 |
| 最近记录: |