线程之间的内存共享

huangapple go评论127阅读模式
英文:

Memory sharing between Threads

问题

我有一个情景,我有点困惑。据我所知,每个线程都有一些本地内存。

// SomeArray 中有 100 个元素
ArrayList SomeArray = new ArrayList();
ForkJoinPool forkJoinPool = new ForkJoinPool(8);
forkJoinPool.submit(() -> {
    SomeArray.parallelStream().map(e -> {
        A a = new A();
        // 执行一些操作
    });
});
class A {

}

所以对于上面的代码,每个线程将创建一个类A的不同对象,并且它们将仅对该对象进行操作。我不认为这会导致任何数据不一致。我有两种情况,但我不确定哪种是正确的。

情况1- 如果两个线程共享同一内存
那么假设一个线程使用引用"a"创建了一个类A的对象,并开始执行一些操作,然后另一个线程使用相同的引用名称创建了一个新对象,但现在"a"开始指向堆中的其他内存。由于"a"存在于共享内存中,因此现在"a"将指向不同的内存。因此,线程1执行的操作将开始反映在另一个对象中。

情况2- 如果两个线程将变量"a"存储在本地内存中
那么两个线程将创建不同的对象,并且由于"a"引用存在于本地内存中,它们之间不会重叠。

简而言之,线程1的"a"变量和线程2的"a"变量将具有相同的内存引用吗?

英文:

I have a scenario where I am confused little bit. As per my knowledge every thread has some local memory.

// 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{

}

So for above code each thread will create a diff object of class A and they will work on that only. I don't think it should cause any data inconsistency. I have 2 cases here but I am not sure which one is right<br>
Case 1- If both threads are sharing the same memory<br>
Then suppose One Thread creates a object of class A with reference "a" and starts performing some action and then another thread creates a new object with same reference name but now "a" starts pointing to other memory in heap. As "a" is present in shared memory so now "a" will point to diff memory. So Actions that are being performed by thread 1 will start reflecting in other Object.<br>
Case 2- If both threads are storing variable "a" in local memory<br>
Then both threads will create diff objects and as "a" reference is present in local memory So there will be no overlap between them.<br>
So in short will thread 1 "a" variable and thread 2 "a" variable will have same memory reference???

答案1

得分: 3

线程没有自己的内存来存储对象。但是当一个方法执行时,该方法执行会分配自己的堆栈帧。堆栈帧可以存储基本类型和对堆分配对象的引用。

在你的代码中,变量a是在闭包执行的块内创建的,a是一个引用,它在堆栈帧上,并且只有执行该闭包的线程可以看到它。每次闭包执行时,它都会获得自己的堆栈帧和自己的a变量。

每个类型为A的对象都是在堆上创建的,堆是跨线程共享的。但是只有当前线程可以看到由该线程执行的方法中的局部变量。

(闭包可以访问其环境中声明的字段。这意味着如果你在声明局部变量a的闭包内嵌套了另一个闭包,那么嵌套的闭包可以访问该a,即使它本来应该超出作用域。因此,你可以创建一个嵌套闭包的情况,多个线程可以看到一个局部变量。但是发布的代码没有这样做。)

英文:

Threads do not have their own memory to use to store objects. But when a method executes, that method execution has its own stackframe allocated to it. The stackframe can store primitives and references to heap-allocated objects.

In your code the variable a is created within a block executed by a closure, a is a reference, it is on the stack frame and only the thread executing that closure can see it. Each time the closure executes it gets its own stackframe and its own a variable.

Each object of type A is created on the heap which is shared across threads. But only the current thread sees the local variables in a method executed by that thread.

(A closure can access fields declared in its environment. That means if you nested yet another closure inside the closure declaring a local a, then the nested closure could access that a, even if it would otherwise have gone out of scope. So you can create a situation with nested closures where more than one thread can see a local variable. But the posted code doesn't do that.)

答案2

得分: 0

根据我的了解,每个线程都有一些本地内存。

在Java语言中,没有"内存"这个概念。只有在描述JVM的内部工作原理时,或者在使用其他语言(如C++)编写通过Java本地接口(Java Native Interface)与Java代码通信的本地代码时,才需要讨论"内存"。

Java语言中有局部变量、静态变量、实例(也称为"对象")以及实例中的字段:

  • 静态变量可以自动地在任何具有访问权限的线程中使用。

  • 局部变量不能在线程之间共享,除非一个被有效地声明为final的局部变量被lambda表达式所捕获,并且lambda表达式的结果在线程之间共享。

  • 字段只有在所属的实例被共享时才会被共享。

  • 实例可以显式地从一个线程传递给另一个线程。用于启动新线程的Runnable对象会自动在新线程和创建它的线程之间共享。其他实例可以通过已经被共享的实例的字段来进行共享。例如,共享的Runnable对象可以具有一个字段,该字段引用一个BlockingQueue。该字段会被共享,因为Runnable是共享的。因此,该字段所引用的队列也会被共享,通过队列传递的任何对象也会成为共享对象。

英文:

> As per my knowledge every thread has some local memory.

There is no "memory" in the Java language. "Memory" is something that you only need to talk about if you are describing the internals of a JVM or, maybe, if you are writing native code in some other language such as C++ with which your Java code will communicate via the Java Native Interface.

The Java language has local variables, static variables, instances (a.k.a., "objects",) and fields within instances:

  • static variables are automatically available to any thread that executes code that has permission to access the variable.

  • Local variables cannot be shared between threads, *except* when an effectively final local variable is captured by a lambda expression, and the result of the lambda is shared between threads.

  • A field is shared if and only if the instance to which it belongs is shared.

  • Instances can be explicitly passed from one thread to another. The Runnable object that is used to start a new thread is automatically shared between the new thread and the thread that created it. Other instances can be made available for sharing via the fields of instances that already are shared. For example The shared Runnable object could have a field that refers to a BlockingQueue. The field would be shared because the Runnable is shared. The queue to which the field refers thus would be shared, and any object that is passed through the queue also becomes a shared object.

huangapple
  • 本文由 发表于 2023年8月9日 02:06:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76862157.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定