提问者:小点点

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


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

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

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

我故意不使用synchronized关键字。

谢啦


共3个答案

匿名用户

对所有局部变量(方法中定义的变量)都将位于它们自己的堆栈框架中。因此,只要引用没有脱离作用域(方法),它们将是线程安全的

注意:如果本地引用转义了该方法(作为另一个方法的参数),或者某个方法在某些类级或实例级字段上工作,那么它不是线程安全的。

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

不,只会有一个方法,每个线程共享相同的方法。但是每个线程都有自己的堆栈框架,局部变量将在该线程的堆栈框架上。即使您在本地对象上使用同步,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");

}

匿名用户

您必须将正在运行的代码和正在处理的数据分开。

该方法是由每个线程执行的代码。如果该代码包含一条语句,如inti=5,该语句定义了一个新变量i,并将其值设置为5,则每个线程将创建该变量。

多线程的问题不在于公共代码,而在于公共数据(和其他公共资源)。如果公共代码访问在别处创建的某个变量j,则所有线程将访问相同的变量j,即相同的数据。如果其中一个线程在其他线程读取时修改共享数据,则可能会发生各种错误。

现在,关于您的问题,只要您的变量在bar()中定义,并且bar()不访问某些公共资源(如文件),那么您的代码就应该是线程安全的。

匿名用户

您应该发布一些示例代码,以确保我们理解用例。

对于此示例:

public class Test {
    private String varA;

    public void doSomething() {
        String varB;

    }
}

如果在本例中不修改varA,而只修改varB,则本例是线程安全的。

但是,如果创建或修改varA并依赖于它的状态,则该方法不是线程安全的。