如果我有一个对象A的实例并且它有一个实例方法foo(),只有在该方法中创建和使用的变量,即使许多线程访问同一个实例,该方法的线程也是安全的吗?
如果是,如果对象A上的实例方法bar()创建了许多线程并在上述文本中调用方法foo(),这仍然适用吗?
这是否意味着每个线程都获得该方法的“副本”,即使它属于同一个实例?
我故意不使用synchronized关键字。
由于
答案 0 :(得分:6)
是。所有局部变量(在方法中定义的变量)都将在它们自己的Stack帧上。因此,如果引用不是转义范围(方法),它们将是线程安全的
注意:如果 local 引用转义方法(作为另一个方法的参数)或方法适用于某些类级别或实例级别字段,那么它不线程安全。
这是否意味着每个帖子都会得到一个"副本"该方法即使属于同一个实例
不,只有一个方法。每个线程共享相同的方法。但是每个Thread都有自己的Stack Frame,局部变量将在该线程的Stack帧上。即使您在本地对象上使用同步, Escape Analysis 也证明JVM将优化您的代码并删除所有类型的同步。
示例:
public static void main(String[] args) {
Object lock = new Object();
synchronized (lock) {
System.out.println("hello");
}
}
将有效地转换为:
public static void main(String[] args) {
Object lock = new Object(); // JVm might as well remove this line as unused Object or instantiate this on the stack
System.out.println("hello");
}
答案 1 :(得分:2)
您必须将正在运行的代码与正在处理的数据分开。
该方法是代码,由每个线程执行。如果该代码包含诸如int i=5
之类的语句,该语句定义了一个新变量i,并将其值设置为5,那么每个线程都将创建该变量。
多线程的问题不在于公共代码,而在于公共数据(以及其他常见资源)。如果公共代码访问在别处创建的某个变量j
,则所有线程将访问相同的变量j
,即相同的数据。如果其中一个线程修改共享数据而其他线程正在读取,则可能发生各种错误。
现在,关于你的问题,你的代码应该是线程安全的,只要你的变量在bar()中定义,而bar()不能访问某些公共资源,如文件。
答案 2 :(得分:0)
您应该发布一些示例代码,以确保我们了解用例。
对于这个例子:
public class Test {
private String varA;
public void doSomething() {
String varB;
}
}
如果您在此示例中没有做任何修改varA
的操作而只修改varB
,则此示例为线程安全。
但是,如果您创建或修改varA
并依赖于其状态,则该方法不线程安全。