什么使一个方法线程安全? 规则是什么?
是否有什么使方法线程安全的总体规则/准则? 我知道可能有一百万次的一次性情况,但是一般情况呢? 这是简单的吗?
- 如果一个方法只访问局部variables,它是线程安全的。
是吗? 这也适用于静态方法吗?
@Cybis提供的一个答案是:
局部variables不能在线程间共享,因为每个线程都有自己的栈。
这是静态方法的情况呢?
如果一个方法传递一个引用对象,那么这是否会破坏线程的安全性? 我已经做了一些研究,并且在某些情况下有很多,但是我希望能够通过使用一些规则来定义遵循的准则,以确保方法是线程安全的。
所以,我想我的最终问题是:“是否有一个定义线程安全方法的规则列表?如果是,它们是什么?
编辑
这里有很多好的一点。 我想这个问题的真正答案是:“确保线程安全没有简单的规则。” 凉。 精细。 但总的来说,我认为接受的答案提供了一个好的,简短的总结。 总有例外。 就这样吧。 我可以忍受这一点。
如果一个方法(实例或静态)只引用在该方法范围内的variables,那么它是线程安全的,因为每个线程都有自己的栈:
在这种情况下,多个线程可以同时调用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; } }
如果方法调用只引用本地作用域variables的其他类方法,也是如此:
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; } }
如果某个方法访问任何(对象状态)属性或字段(实例或静态),则需要使用locking来确保值不会被其他线程修改。
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; } }
你应该知道传入方法的参数不是结构体或者是不可变的,都可能被方法范围之外的另一个线程所突变。
为了确保正确的并发性,你需要使用locking。
有关更多信息,请参阅locking语句C#引用和ReadWriterLockSlim 。
锁主要用于一次提供一个function,
ReadWriterLockSlim
是有用的,如果你需要多个读者和单个作家。
如果一个方法只访问局部variables,它是线程安全的。 是吗?
绝对不是。 你可以编写一个只有一个局部variables的程序,这个局部variables可以从一个线程访问,但是不是线程安全的:
https://stackoverflow.com/a/8883117/88656
这也适用于静态方法吗?
绝对不。
@Cybis提供的一个答案是:“线程之间不能共享局部variables,因为每个线程都有自己的堆栈”。
绝对不。 局部variables的区别特征是它只能在本地范围内可见 ,而不是在临时池上分配 。 从两个不同的线程访问相同的局部variables是完全合法的,也是可能的。 您可以通过使用匿名方法,lambdaexpression式,迭代器块或asynchronous方法来完成此操作。
这是静态方法的情况呢?
绝对不。
如果一个方法传递一个引用对象,那么这是否会破坏线程的安全性?
也许。
我已经做了一些研究,并且在某些情况下有很多,但是我希望能够通过使用一些规则来定义遵循的准则,以确保方法是线程安全的。
你将不得不学着忍受失望。 这是一个非常困难的课题。
所以,我想我的最终问题是:“是否有定义线程安全方法的规则的简短列表?
不。 正如你从前面的示例中看到的, 一个空方法可以是非线程安全的 。 你可能会问:“是否有一个确保方法正确的规则列表”。 不,那里没有。 线程安全只不过是一种极其复杂的正确性。
而且,你问这个问题的事实表明你对线程安全的基本误解。 线程安全是全球性的 ,而不是程序的本地特性。 之所以这么难是因为你必须对整个程序的线程行为有一个全面的了解才能保证它的安全。
再看看我的例子: 每一种方法都是微不足道的 。 这种方法是在“全局”层面上相互影响,使程序陷入僵局。 你不能看每一种方法,并检查它是“安全”,然后期望整个程序是安全的,不仅如此,你可以得出结论,因为你的房子是由100%的非空心砖,房子也是非中空。 房子的空洞是整个事物的全球性特征,而不是其各部分特性的总和。
没有硬性规定。
这里有一些规则来使代码线程在.NET中安全,为什么这些规则不是很好:
- 函数和它调用的所有函数必须是纯的(没有副作用)并使用局部variables。 尽pipe这会使你的代码是线程安全的,但是在.NET中这个限制也可以做很less有趣的事情。
- 每个在一个公共对象上运行的函数都必须
lock
一个共同的东西。 所有的锁必须按照相同的顺序完成。 这将使代码线程安全,但速度会非常慢,而且您可能不会使用多个线程。 - …
没有规则可以使代码线程安全,唯一可以做的就是确保你的代码无论主动执行多less次都能正常工作,每个线程都可以随时中断,每个线程都在它自己的状态/位置,以及访问公共对象的每个函数(静态或其他)。
它必须被同步,使用对象锁,无状态或不可变。
链接: http : //docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html