Java 局部变量中引用的实例变量。内存、线程安全和终结
Java Instance Variable referred within local variable. Memory, thread safety and finalization
我有 class 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 是在哪里创建的?在堆?声明为实例变量的映射是否存在线程安全问题。
当局部变量被垃圾回收时,我假设 map 也被垃圾回收。如果我错了,请纠正。
注意:我知道在多线程环境中有实例变量时会出现数据损坏
然而,这是略有不同的情况[=12=]
OtherClass
对象将在堆上创建,并且对该对象的引用将在堆栈上创建。由于 stack confinement
,这段代码是完全线程安全的。只有当对象的状态在多个线程之间共享时,才会出现线程安全问题。由于此对象只能由调用该方法的线程访问,因此它不是共享的。一旦堆栈弹出,对象将被垃圾回收。
When a thread executes the method meth1() where does Map is created?
in heap?
是的。你用 new Whatever()
创建的所有东西都存储在堆上,包括 OtherClass
实例和它的 HashMap
(因为它的初始化包括 new HashMap<>()
表达式)。每次执行 new Whatever()
时,您都会在堆上获得一个全新的实例。
Is there thread safety issues wrt to the map declared as instance
variable.
不,在你的例子中不是。仅当多个线程访问 OtherClass
的同一个实例时,线程安全才可能成为问题。在您的情况下,每个执行线程都会创建其单独的 OtherClass
实例(在局部变量 other
中),仅使用该实例,并且不会将其分发到其他线程可能看到它的任何地方。
When local variable is garbage collected, I assume map is
also garbage collected.
可以,只要您不添加将地图分发给软件其他部分的代码。
当实例不再被任何 "live" variable/parameter/object/... 引用时,实例将被垃圾回收...在您的情况下,ops
HashMap 仅被引用(存储) ops
其封闭 OtherClass
实例的字段。因此,当此实例不再可访问时,Map 也将变得不可访问,从而准备好进行垃圾收集。
一句话:垃圾收集不会在某些东西变得不可访问的同一时刻发生,它是由一些精心设计的优化算法安排的。您唯一可以确定的是,它会在您 运行 内存不足之前发生。
Note: I know there are data corruption when we have instance variables
within multi-threaded environment However this is slightly difference
scenario
只有相反的方向才是正确的:如果没有实例或 class 字段,则无法 运行 进入线程安全/数据损坏问题。
正确的是:如果在多线程设置中使用实例或class字段,则必须小心。但是例如只读实例字段(仅在构造函数中设置且以后永远不会更改的字段)通常是安全的。
我有 class 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 是在哪里创建的?在堆?声明为实例变量的映射是否存在线程安全问题。 当局部变量被垃圾回收时,我假设 map 也被垃圾回收。如果我错了,请纠正。
注意:我知道在多线程环境中有实例变量时会出现数据损坏 然而,这是略有不同的情况[=12=]
OtherClass
对象将在堆上创建,并且对该对象的引用将在堆栈上创建。由于 stack confinement
,这段代码是完全线程安全的。只有当对象的状态在多个线程之间共享时,才会出现线程安全问题。由于此对象只能由调用该方法的线程访问,因此它不是共享的。一旦堆栈弹出,对象将被垃圾回收。
When a thread executes the method meth1() where does Map is created? in heap?
是的。你用 new Whatever()
创建的所有东西都存储在堆上,包括 OtherClass
实例和它的 HashMap
(因为它的初始化包括 new HashMap<>()
表达式)。每次执行 new Whatever()
时,您都会在堆上获得一个全新的实例。
Is there thread safety issues wrt to the map declared as instance variable.
不,在你的例子中不是。仅当多个线程访问 OtherClass
的同一个实例时,线程安全才可能成为问题。在您的情况下,每个执行线程都会创建其单独的 OtherClass
实例(在局部变量 other
中),仅使用该实例,并且不会将其分发到其他线程可能看到它的任何地方。
When local variable is garbage collected, I assume map is also garbage collected.
可以,只要您不添加将地图分发给软件其他部分的代码。
当实例不再被任何 "live" variable/parameter/object/... 引用时,实例将被垃圾回收...在您的情况下,ops
HashMap 仅被引用(存储) ops
其封闭 OtherClass
实例的字段。因此,当此实例不再可访问时,Map 也将变得不可访问,从而准备好进行垃圾收集。
一句话:垃圾收集不会在某些东西变得不可访问的同一时刻发生,它是由一些精心设计的优化算法安排的。您唯一可以确定的是,它会在您 运行 内存不足之前发生。
Note: I know there are data corruption when we have instance variables within multi-threaded environment However this is slightly difference scenario
只有相反的方向才是正确的:如果没有实例或 class 字段,则无法 运行 进入线程安全/数据损坏问题。
正确的是:如果在多线程设置中使用实例或class字段,则必须小心。但是例如只读实例字段(仅在构造函数中设置且以后永远不会更改的字段)通常是安全的。