Bob*_*orn 143 c# thread-safety
是否存在使方法线程安全的整体规则/指南?我知道可能有一百万次一次性情况,但一般情况如何呢?这很简单吗?
是吗?这也适用于静态方法吗?
@Cybis提供的一个答案是:
局部变量不能在线程之间共享,因为每个线程都有自己的堆栈.
静态方法也是如此吗?
如果方法传递给引用对象,那是否会破坏线程的安全性?我做了一些研究,并且有很多关于某些情况的研究,但我希望能够通过使用一些规则来定义遵循的指导方针,以确保方法是线程安全的.
所以,我想我的最终问题是:"是否有一个简短的规则列表定义了一个线程安全的方法?如果是这样,它们是什么?"
编辑这里
有很多好处.我认为这个问题的真正答案是:"没有简单的规则来确保线程安全." 凉.精细.但总的来说,我认为接受的答案提供了一个很好的简短摘要.总有例外.就这样吧.我可以忍受这一点.
Tre*_*ley 130
如果方法(实例或静态)仅引用该方法中作用域的变量,那么它是线程安全的,因为每个线程都有自己的堆栈:
在这种情况下,多个线程可以ThreadSafeMethod
同时调用而不会出现问题.
public class Thing
{
public int ThreadSafeMethod(string parameter1)
{
int number; // each thread will have its own variable for number.
number = parameter1.Length;
return number;
}
}
Run Code Online (Sandbox Code Playgroud)
如果该方法调用仅引用本地范围变量的其他类方法,则也是如此:
public class Thing
{
public int ThreadSafeMethod(string parameter1)
{
int number;
number = this.GetLength(parameter1);
return number;
}
private int GetLength(string value)
{
int length = value.Length;
return length;
}
}
Run Code Online (Sandbox Code Playgroud)
如果方法访问任何(对象状态)属性或字段(实例或静态),则需要使用锁定以确保不会由其他线程修改这些值.
public class Thing
{
private string someValue; // all threads will read and write to this same field value
public int NonThreadSafeMethod(string parameter1)
{
this.someValue = parameter1;
int number;
// Since access to someValue is not synchronised by the class, a separate thread
// could have changed its value between this thread setting its value at the start
// of the method and this line reading its value.
number = this.someValue.Length;
return number;
}
}
Run Code Online (Sandbox Code Playgroud)
您应该知道,传入方法的任何不是结构或不可变的参数都可以被方法范围之外的另一个线程变异.
要确保正确的并发性,您需要使用锁定.
有关详细信息,请参阅lock语句C#reference和ReadWriterLockSlim.
锁定对于一次提供一个功能
ReadWriterLockSlim
非常有用,如果您需要多个读取器和单个编写器,则非常有用.
Eri*_*ert 103
如果方法只访问局部变量,那么它是线程安全的.是吗?
绝对不是.您可以编写一个程序,只有一个本地变量从一个线程访问,但该线程不是线程安全的:
这也适用于静态方法吗?
绝对不.
@Cybis提供的一个答案是:"不能在线程之间共享局部变量,因为每个线程都有自己的堆栈."
绝对不.局部变量的区别特征是它只能在本地范围内可见,而不是在临时池上分配.从两个不同的线程访问相同的局部变量是完全合法的.您可以使用匿名方法,lambdas,迭代器块或异步方法来完成此操作.
静态方法也是如此吗?
绝对不.
如果方法传递给引用对象,那是否会破坏线程的安全性?
也许.
我做了一些研究,并且有很多关于某些情况的研究,但我希望能够通过使用一些规则来定义遵循的指导方针,以确保方法是线程安全的.
你将不得不学会以失望的方式生活.这是一个非常困难的主题.
所以,我想我的最终问题是:"是否有一个简短的规则列表定义了一个线程安全的方法?
不.正如您在前面的示例中看到的,空方法可以是非线程安全的.您不妨问"是否有一个确保方法正确的规则的简短列表".不,那里没有.线程安全只不过是一种非常复杂的正确性.
此外,您提出问题的事实表明您对线程安全的基本误解.线程安全是程序的全局属性,而不是本地属性.之所以难以做到,是因为您必须完全了解整个程序的线程行为,以确保其安全性.
再看看我的例子:每个方法都是微不足道的.这是方法在"全局"级别相互交互的方式,使程序陷入僵局.您无法查看每种方法并将其视为"安全",然后期望整个程序是安全的,不仅仅是您可以得出结论,因为您的房子是由100%非空心砖制成的房子也是非中空.房屋的空心是整个房屋的整体属性,而不是其各部分属性的集合.
没有硬性规定.
以下是使.NET中的代码线程安全的一些规则以及为什么这些不是好的规则:
lock
上运行的每个函数都必须是常见的.所有锁必须以相同的顺序完成.这将使代码线程安全,但它将非常慢,并且您可能不会使用多个线程.没有规则可以使代码线程安全,你唯一能做的就是确保你的代码无论多少次被主动执行都会工作,每个线程都可以在任何时候中断,每个线程都在它自己的状态/位置,以及访问公共对象的每个函数(静态或其他).