我有一个场景,让我有点困惑。据我所知,每个线程都有一些本地内存。
// 100 elements in SomeArray
ArrayList SomeArray = new ArrayList();
ForkJoinPool forkJoinPool = new ForkJoinPool(8);
forkJoinPool.submit( () ->{
SomeArray.parallelStream().map(e->{
A a= new A();
// perform some action
});
});
class A{
}
因此,对于上面的代码,每个线程都会创建一个 A 类的 diff 对象,并且它们只会处理该对象。我认为这不会导致任何数据不一致。我这里有两个案例,但我不确定哪一个是正确的
情况 1 - 如果两个线程共享相同的内存
然后假设一个线程创建一个具有引用“a”的 A 类对象并开始执行某些操作,然后另一个线程创建一个具有相同引用名称的新对象,但现在“a”开始指向堆中的其他内存。由于“a”存在于共享内存中,因此现在“a”将指向差异内存。因此,线程 1 正在执行的操作将开始反射(reflect)在其他对象中。
情况 2 - 如果两个线程都在本地内存中存储变量“a”
然后两个线程都会创建 diff 对象,并且由于本地内存中存在“a”引用,因此它们之间不会有重叠。
简而言之,线程 1“a”变量和线程 2“a”变量将具有相同的内存引用???
最佳答案
线程没有自己的内存来存储对象。但是当一个方法执行时,该方法执行会分配有自己的堆栈帧。堆栈帧可以存储基元和对堆分配对象的引用。
在您的代码中,变量a
是在闭包执行的 block 内创建的,a
是一个引用,它位于堆栈帧上,并且只有执行该变量的线程关闭就可以看到了。每次执行闭包时,它都会获得自己的堆栈帧和自己的a
变量。
每个 A
类型的对象都是在跨线程共享的堆上创建的。但只有当前线程才能看到该线程执行的方法中的局部变量。
(闭包可以访问在其环境中声明的字段。这意味着如果您在声明本地 a
的闭包中嵌套另一个闭包,那么嵌套的闭包可以访问该 a
,即使它会超出范围。因此,您可以创建一种具有嵌套闭包的情况,其中多个线程可以看到局部变量。但发布的代码不会这样做。)
关于java - 线程之间的内存共享,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76862157/