我有MyClass类,该类具有带变量的方法-OtherClass的实例,如下所示
public class Myclass{
public void meth1(){
OtherClass other = new OtherClass();
other.perform();
}
}
public class OtherClass{
private Map<String, String> ops = new HashMap<>();
public void perform(){
// put/ remove values in ops
}
}
这是一个多线程环境当线程执行方法meth1()时,将在何处创建Map?在堆里?声明为实例变量的映射是否存在线程安全问题。当局部变量被垃圾收集时,我认为地图也是垃圾收集。如果我错了,请纠正。
注意:我知道在多线程环境中有实例变量时,数据会损坏但这是稍微不同的情况
OtherClass
对象将在堆上创建,并且对该对象的引用将在堆栈上创建。由于stack confinement
,此代码是完全线程安全的。仅当在多个线程之间共享对象的状态时,才会出现线程安全问题。由于只能通过调用该方法的线程访问此对象,因此不会共享该对象。一the弹出,该对象将被垃圾回收。
[当线程执行方法meth1()时,将在何处创建Map?在堆中?
是。使用new Whatever()
创建的所有内容都存储在堆中,既包含OtherClass
实例也包含其HashMap
(因为其初始化包括new HashMap<>()
表达式)。每次执行new Whatever()
时,您都会在堆上获得一个全新的实例。
声明为实例的映射是否存在线程安全问题?变量。
不,不在您的示例中。仅当多个线程正在访问OtherClass
的同一实例时,线程安全才可能成为问题。在您的情况下,每个执行线程都会创建其单独的OtherClass
实例(在局部变量other
中),仅使用该实例,并且不会将其分发到其他线程可能看到它的任何位置。
当局部变量被垃圾回收时,我认为map是还垃圾收集。
是,只要您不添加将Map交给软件其他部分的代码。
当实例不再由任何“活动”变量/参数/对象/ ...引用时,将对其进行垃圾回收。在您的情况下,ops
HashMap仅由其所在的ops
字段引用(存储) OtherClass
实例。因此,当该实例不再可访问时,Map也将不可访问,从而可以进行垃圾回收。
备注:垃圾收集不会在某些东西变得无法到达的那一瞬间发生,而是通过精心设计的优化算法进行调度的。您唯一可以确定的是,它将在内存用完之前发生。
注意:我知道当我们有实例变量时,数据会损坏在多线程环境中但是这有点不同场景
这仅是相反的方向:如果没有实例或类字段,就不会遇到线程安全/数据损坏的问题。
事实是:如果在多线程设置中使用实例或类字段,则必须小心。但是例如只读实例字段(您只能在构造函数中设置的字段,以后再也不会更改)通常是安全的。