What Makes a Method Thread-safe? What are the rules?
是否有使方法线程安全的总体规则/准则?我知道可能有一百万个一次性的情况,但一般情况下呢?这很简单吗?
是这样吗?这也适用于静态方法吗?
由CybIS提供的一个答案是:
Local variables cannot be shared among threads because each thread gets its own stack.
静态方法也是这样吗?
如果一个方法被传递给一个引用对象,这会破坏线程安全吗?我做过一些研究,关于某些案例有很多,但是我希望能够通过使用一些规则来定义要遵循的准则,以确保方法是线程安全的。
所以,我想我的终极问题是:"是否有一个简短的规则列表来定义线程安全方法?如果是,他们是什么?"
编辑< BR/>这里有很多好的地方。我认为这个问题的真正答案是:"没有简单的规则来确保线程安全。"酷。好的。但总的来说,我认为被接受的答案提供了一个好的、简短的总结。总有例外。就这样吧。我可以忍受。
如果一个方法(实例或静态)只引用该方法范围内的变量,那么它是线程安全的,因为每个线程都有自己的堆栈:
在这种情况下,多个线程可以同时调用
1 2 3 4 5 6 7 8 9 | public class Thing { public int ThreadSafeMethod(string parameter1) { int number; // each thread will have its own variable for number. number = parameter1.Length; return number; } } |
如果该方法调用只引用本地作用域变量的其他类方法,则也是如此:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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; } } |
如果方法访问任何(对象状态)属性或字段(实例或静态),则需要使用锁来确保值不会被其他线程修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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; } } |
您应该知道,传递给方法的任何参数(既不是结构也不是不可变的)都可能被方法范围之外的另一个线程改变。
为了确保适当的并发性,您需要使用锁定。
有关更多信息,请参阅lock statement c reference和readwriterlockslim。
锁主要用于提供一次一个的功能,
如果您需要多个读者和单个作者,
If a method only accesses local variables, it's thread safe. Is that it?
绝对不是。您可以编写一个程序,其中只有一个本地变量可以从单个线程访问,但该线程不是线程安全的:
https://stackoverflow.com/a/8883117/88656
Does that apply for static methods as well?
绝对不是。
One answer, provided by @Cybis, was:"Local variables cannot be shared among threads because each thread gets its own stack."
绝对不是。局部变量的区别特性是它只能从局部范围内可见,而不是在临时池上分配。从两个不同的线程访问相同的本地变量是完全合法的。可以通过使用匿名方法、lambdas、迭代器块或异步方法来实现这一点。
Is that the case for static methods as well?
绝对不是。
If a method is passed a reference object, does that break thread safety?
也许吧。
I've done some research, and there is a lot out there about certain cases, but I was hoping to be able to define, by using just a few rules, guidelines to follow to make sure a method is thread safe.
你必须学会忍受失望。这是一门很难的学科。
So, I guess my ultimate question is:"Is there a short list of rules that define a thread-safe method?
不。正如您在前面的示例中看到的,空方法可以是非线程安全的。您不妨问"是否有一个简短的规则列表可以确保方法是正确的"。不,没有。线程安全只是一种极其复杂的正确性。
此外,您提出问题的事实表明您对线程安全的基本误解。线程安全是全局的,而不是程序的本地属性。之所以如此难以正确处理,是因为您必须完全了解整个程序的线程行为,以确保其安全性。
再来看看我的例子:每个方法都是琐碎的。正是这些方法在"全局"级别上相互作用的方式导致了程序死锁。你不能把每种方法都看成是"安全的",然后期望整个程序是安全的,这比你能得出的结论更重要,因为你的房子是由100%的非空心砖建造的,所以房子也是非空心的。空旷的房子是一个整体的全球性财产,而不是其各部分财产的总和。
没有硬性规定。
以下是一些使.NET中的代码线程安全的规则,以及为什么这些规则不好:
没有使代码线程安全的规则,您唯一能做的就是确保您的代码可以工作,无论它被主动执行多少次,每个线程都可以在任何点被中断,每个线程都处于自己的状态/位置,这对于访问公共对象的每个函数(静态或其他)都是如此。
它必须使用对象锁、无状态或不可变进行同步。
链接:http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html