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