java 的多线程问题 ?

如图所示, 位置 2 和位置3 为什么可以访问 位置1 (也就是主线程)的 point 局部变量 ?
毕竟 位置 2 和位置3 是另外两个线程啊 !!

当我加上 第10行代码后,thread1 和 thead2 中都不能访问主线程中的point 了。我知道这是内部类的“事实最终变量” 的限制。

如下图所示,就是我不理解的地方。(在 “栈内存” 层面)

我的猜测:之所以 thread1 和 tread2 这两个新的线程并没有初始化 point 这个变量 但是还能使用的原因是因为 Runnable 的两个实现类 内部都各自 生成了一个 point 实例变量 ? (虽然书上的解释是针对局部内部类,针对外面的方法执行完毕局部变量就不复存在的原因, 但是我不知道 多线程 能不能也可以同样这样解释)。


回答:

堆栈封闭:局部变量,无并发问题,每个线程会各自拷贝一份到各自新建的线程中。

只可使用,不可修改该局部变量的值(因为是复制到新新线程中的,所以只能改副本数据,不能改main函数中局部变量的值)

栈封闭是我们编程当中遇到的最多的线程封闭。什么是栈封闭呢?简单的说就是局部变量。多个线程访问一个方法,此方法中的局部变量都会被拷贝一分儿到线程栈中。所以局部变量是不被多个线程所共享的,也就不会出现并发问题。所以能用局部变量就别用全局的变量,全局变量容易引起并发问题。

    public static void main(String[] args) {

t1();

}

public static void t1() {

AtomicReference<User> user = new AtomicReference<>(new User());

user.set(new User("defaultName"));

Runnable runnable = () -> {

user.set(new User("name1"));

};

Thread thread1 = new Thread(runnable);

Thread thread2 = new Thread(()-> user.set(new User("name2")));

thread1.start();

thread2.start();

System.out.println(user);

}

打印结果:
User(name=defaultName)


回答:

因为对象在堆里
堆是所有线程共享的
所以可以访问


回答:

能不能访问跟在哪个线程创建没有什么关系。

你引用的讨论跟是否多线程貌似也没有关系。


回答:

能否访问变量只与变量的作用域有关,跟在哪一个线程无关。

你这里同处于一个块级作用域,当然能访问到了。

至于跨线程访问同一个变量是否会有“线程安全”问题,这是另一个问题,跟“能否访问”是两码事儿,没有一点儿关系。


回答:

我觉得这不算栈封闭,栈封闭限于对象不能逸出。比如这样。适用于基础数据类型

class User(val name: String){

val c:Int = 0

fun demo(){

Thread{

val b = c

println(b)

}

}

}

即c在怎么改变,也无法对b造成影响。但如果是一个对象。显然结论不成立。第一个回答者的测试在我这里没通过,如果加上thread.join() 就会发现,其实是能够修改,看到之后我真以为不能修改,所以去做了测试。

所以结论就应该是普通的堆调用。堆内存是共享的,所以不需要什么初始化,哪个线程都能使用。至于为什么是final,我觉得可能是为了防止在线程里面随意赋值,导致变量在其他线程里的浅拷贝对象出现错乱。

最后,如果真的对多线程有兴趣,还是推荐《java并发编程实践》 在并发这方面。没有哪本书比这本书更加权威。里面也有关于栈封闭的解释。


回答:

对象是保存在堆里,对象的引用才是在栈里,堆内存是共享的

以上是 java 的多线程问题 ? 的全部内容, 来源链接: utcz.com/p/945542.html

回到顶部