java中单实例方法的线程安全性

时间:2014-08-13 15:06:56

标签: java multithreading

如果我有一个对象A的实例并且它有一个实例方法foo(),只有在该方法中创建和使用的变量,即使许多线程访问同一个实例,该方法的线程也是安全的吗?

如果是,如果对象A上的实例方法bar()创建了许多线程并在上述文本中调用方法foo(),这仍然适用吗?

这是否意味着每个线程都获得该方法的“副本”,即使它属于同一个实例?

我故意不使用synchronized关键字。

由于

3 个答案:

答案 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并依赖于其状态,则该方法线程安全。