方法局部变量和堆栈和堆

在阅读线程安全时,我遇到了这个问题。 如果我是正确的方法,则本地基本元和对象引用位于堆栈内,并且堆栈中引用指向的实际对象位于堆中。

但是,当涉及到方法本地非原始对象初始化时,会不会导致并发问题? 我的意思是如果方法locals非基元生活在堆中,只有指针存在于堆栈中,是不是与实例变量相同?

有人可以帮助我理解这一点....

PS

想想两个线程,每个线程都有自己的堆栈和一堆堆栈。 我所理解的是这两个线程将它们的方法本地原始变量保存在其堆栈中。 我没有这个问题。

但是如果我们有一个非原始方法局部变量的方法呢? 然后,如果该变量的对象存储在堆内部,那么这两个线程将有权访问同一对象,对吗? 所以如果是这样的话会有同步问题。

这就是我要问的。

谢谢


如果两个线程都有对该对象的引用,则它们可以访问相同的对象。 如果你有如下的方法:

public String concat(String a, String b) {
    StringBuilder builder = new StringBuilder();
    builder.append(a);
    builder.append(b);
    return builder.toString();
}

StringBuilder对象确实在堆中,但只有一个线程具有对该对象的引用。 没有其他线程可以引用此StringBuilder。 所以它本质上是线程安全的。

相反,如果您有以下情况:

public String concat(String a, String b) {
    final StringBuilder builder = new StringBuilder();
    new Thread(new Runnable() {
        @Override
        public void run() {
            builder.append("haha!");
        }
    }).start();
    builder.append(a);
    builder.append(b);
    return builder.toString();
}

然后你有一个线程安全问题,因为你是与另一个线程本地创建的对象引用,并且StringBuilder不是线程安全的。


但是如果我们有一个非原始方法局部变量的方法呢? 然后,如果该变量的对象存储在堆内部,那么这两个线程将有权访问同一对象,对吗? 所以如果是这样的话会有同步问题。

我想知道为什么你会认为这两个引用会引用同一个对象。

引用的对象的创建是由新的(或其他类似的方法,但想法是相同的)明确地完成的,

因此,与C ++不同的是,如果您使用Java进行声明

Foo foo;

没有Foo对象实例化。 foo只是一个指向什么都没有的指针。

这会在堆中为你创建一个Foo对象实例。

Foo foo = new Foo();

如果两个线程正在运行这段代码,线程1将在堆栈中有一个Foo引用,并要求在堆中分配一个新的Foo对象,然后将该Foo obj的地址分配给引用foo 。 线程2也是这样做的。 请注意,线程2也要求分配一个新的Foo对象,它将成为线程1分配的不同对象。

这是基本的(并且非常简化)的想法。


But what if we have a method with non primitive method local variables ? Then if the object for that variable is stored inside the heap, both the threads will have the access to the same object, won't they ? So if that's the case there would be Sync problems

您部分回答了您自己的问题。该引用值存储在堆栈中,但实际的对象内容存储在堆中,并且当您调用新的Object()时,每个线程创建将存储在堆中的不同新对象,并且每个线程访问使用存储在其自己堆栈中的引用值创建的对象

链接地址: http://www.djcxy.com/p/79085.html

上一篇: Method local variables and stack and heap

下一篇: static objects vs. stack