简体   繁体   English

确保Java方法是线程安全的

[英]to ensure a java method is thread safe

is it enough to use only local variables and no instance variables. 仅使用局部变量而不使用实例变量是否足够? Thus only using memory on the stack (per thread). 因此仅使用堆栈上的内存(每个线程)。

But what happens when you create a new MyObject that is local to the method. 但是,当您创建方法本地的新MyObject时会发生什么。 Doesn't the new object get created on the heap ? 新对象不是在堆上创建的吗? Is it thread safe becuase the reference to it is local (thread safe) ? 它是线程安全的,因为对其的引用是本地的(线程安全)吗?

It is thread safe because if it is only referenced by variables in that particular method (it is, as you said, a local variable), then no other threads can possibly have a reference to the object, and therefore cannot change it. 它是线程安全的,因为如果仅由该特定方法中的变量引用(如您所说,它是局部变量),则其他任何线程都不可能引用该对象,因此无法更改该对象。

Imagine you and I are pirates (threads). 想象你和我是海盗(线程)。 You go and bury your booty (the object) on an island (the heap), keeping a map to it (the reference). 您去将赃物(对象)埋在岛(堆)上,并保留一张地图(参考)。 I happen to use the same island for burying my booty, but unless you give me your map, or I go digging all over the island (which isn't allowed on the island of Java), I can't mess with your stash. 我碰巧用同一个岛埋藏我的战利品,但是除非您给我您的地图,否则我将在整个岛上进行挖掘(在Java岛上是不允许的),所以我不会弄乱您的藏身之处。

Your new MyObject is thread-safe because each call to the method will create its own local instance on the heap. 您的新MyObject是线程安全的,因为对方法的每次调用都会在堆上创建自己的本地实例。 None of the calls refer to a common method; 没有一个调用引用一个通用方法。 if there are N calls, that means N instances of MyObject on the heap. 如果有N个调用,则表示堆上有N个MyObject实例。 When the method exits, each instance is eligible for GC as long as you don't return it to the caller. 方法退出后,只要您不将其返回给调用方,每个实例都可以使用GC。

Well, let me ask you a question: does limiting your method to local variables mean your method can't share a resource with another thread? 好吧,让我问一个问题:将方法限制为局部变量是否意味着您的方法无法与另一个线程共享资源? If not, then obviously this isn't sufficient for thread safety in general. 如果不是这样,那么显然这通常不足以保证线程安全。

If you're worried about whether another thread can modify an object you created in another thread, then the only thing you need to worry about is never leaking a reference to that object out of the thread. 如果您担心另一个线程是否可以修改您在另一个线程中创建的对象,那么您唯一需要担心的就是永远不要从线程中泄漏对该对象的引用。 If you achieve that, your object will be in the heap, but no other thread will be able to reference it so it doesn't matter. 如果实现了这一点,则对象将在堆中,但是没有其他线程能够引用它,所以没关系。

Edit 编辑

Regarding my first statement, here's a method with no instance variables: 关于我的第一条语句,这是一个没有实例变量的方法:

public void methodA() {
    File f = new File("/tmp/file");
    //...
}

This doesn't mean there can't be a shared resource between two threads :-). 这并不意味着两个线程之间不能共享资源:-)。

Threre's no way to other threads to access such object reference. Threre无法访问其他线程来访问此类对象引用。 But if that object is not thread-safe, then the overall thread-safety is compromised. 但是,如果该对象不是线程安全的,则将损害总体线程安全。

Consider for example that MyObject is a HashMap. 例如,考虑MyObject是HashMap。

The argument that if it's in the heap, it's not thread-safe, is not valid. 如果它在堆中不是线程安全的,则该论点无效。 The heap is not accessible via pointer arithmetic, so it doesn't affect where the object is actually stored (besides ThreadLocal's). 不能通过指针算法访问堆,因此它不会影响对象的实际存储位置(除了ThreadLocal之外)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM