Java实例变量在局部变量内引用。内存,线程安全性和终结处理

问题描述 投票:0回答:2

我有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?在堆里?声明为实例变量的映射是否存在线程安全问题。当局部变量被垃圾收集时,我认为地图也是垃圾收集。如果我错了,请纠正。

注意:我知道在多线程环境中有实例变量时,数据会损坏但这是稍微不同的情况

java garbage-collection java-threads java-memory-model
2个回答
1
投票

OtherClass对象将在堆上创建,并且对该对象的引用将在堆栈上创建。由于stack confinement,此代码是完全线程安全的。仅当在多个线程之间共享对象的状态时,才会出现线程安全问题。由于只能通过调用该方法的线程访问此对象,因此不会共享该对象。一the弹出,该对象将被垃圾回收。


0
投票

[当线程执行方法meth1()时,将在何处创建Map?在堆中?

是。使用new Whatever()创建的所有内容都存储在堆中,既包含OtherClass实例也包含其HashMap(因为其初始化包括new HashMap<>()表达式)。每次执行new Whatever()时,您都会在堆上获得一个全新的实例。

声明为实例的映射是否存在线程安全问题?变量。

不,不在您的示例中。仅当多个线程正在访问OtherClass的同一实例时,线程安全才可能成为问题。在您的情况下,每个执行线程都会创建其单独的OtherClass实例(在局部变量other中),仅使用该实例,并且不会将其分发到其他线程可能看到它的任何位置。

当局部变量被垃圾回收时,我认为map是还垃圾收集。

是,只要您不添加将Map交给软件其他部分的代码。

当实例不再由任何“活动”变量/参数/对象/ ...引用时,将对其进行垃圾回收。在您的情况下,ops HashMap仅由其所在的ops字段引用(存储) OtherClass实例。因此,当该实例不再可访问时,Map也将不可访问,从而可以进行垃圾回收。

备注:垃圾收集不会在某些东西变得无法到达的那一瞬间发生,而是通过精心设计的优化算法进行调度的。您唯一可以确定的是,它将在内存用完之前发生。

注意:我知道当我们有实例变量时,数据会损坏在多线程环境中但是这有点不同场景

这仅是相反的方向:如果没有实例或类字段,就不会遇到线程安全/数据损坏的问题。

事实是:如果在多线程设置中使用实例或类字段,则必须小心。但是例如只读实例字段(您只能在构造函数中设置的字段,以后再也不会更改)通常是安全的。

© www.soinside.com 2019 - 2024. All rights reserved.