JAVA线程(不同栈)同步

我有一个关于由多个线程执行的代码同步的问题:

I have a question regarding synchronization of code that is executed by several threads:

据我所知,每个线程都有自己的堆栈,因此,非静态变量存在于每个线程的内存中的不同位置(对于 X 个线程,有 X 个堆栈包含所有非静态变量).那么为什么需要同步任何东西呢?

As far as I know each thread has its own stack, hence, non-static variables exist in different locations in the memory for each thread (for X threads there are X stacks that include all non-static variables). So why there's a need to synchronize anything?

我的意思是,如果线程执行的代码包含某个类变量 v1,那么每个线程都有自己的 v1实例"(不同的内存地址),并且没有其他线程可以触摸"它……不是是吗?

I mean, if the code that the threads execute includes some class variable v1, then each thread has its own "instance" of v1 (different memory address), and no other thread can "touch" it... isn't it so?

推荐答案

非静态变量存在于每个线程内存的不同位置

non-static variables exist in different locations in the memory for each thread

这不是真的,所以回答

如果线程执行的代码包括一些类变量v1,那么每个线程都有自己的实例".v1(不同的内存地址),没有其他线程可以触摸";它……是不是这样

if the code that the threads execute includes some class variable v1, then each thread has its own "instance" of v1 (different memory address), and no other thread can "touch" it... isn't it so

没有.线程可以接触到由其他线程分配和修改的对象实例,程序员有责任确保这不会影响程序的正确性.

is no. Threads can touch object instances allocated and modified by other threads and the burden is on the programmer to ensure this does not affect program correctness.

类成员变量存在于每个类实例的内存中的一个位置,而不是每个线程.确实,在 内存屏障之间(想想开始 { 和end } of synchronized),线程可能有一个对象状态的缓存,但这与强制每个线程存储的语言不同.每个线程的内存"是它的堆栈,它不包含对象成员* -- 仅对对象的引用.

Class member variables exist in a single place in memory per-class instance, not per thread. It is true that between memory barriers (think the start { and end } of synchronized), that a thread may have a cache of the state of an object, but that is not the same as the language mandating per-thread storage. The "memory for each thread" is its stack which does not contain object members* -- only references to objects.

最好的想法是每个对象在堆上都有一个位置,但可能同时发生涉及该内存位置的多个读取和写入.

The best way to think of it is that there is one location on the heap for each object, but that there might be multiple reads&|writes involving that memory location happening at the same time.

如果你听说线程在堆的不同部分分配对象,我知道你会如何得出你所做的结论.一些 JVM 进行了优化,他们执行 线程本地分配 但这不会阻止其他线程访问这些对象.

I can see how you would come to the conclusions you did if you heard that threads allocate objects in different parts of the heap. Some JVMs have an optimization whereby they do thread-local allocation but that does not prevent other threads from accessing those objects.

线程局部分配

如果真正如清单 1 所示实现分配器,共享 heapStart 字段将很快成为一个重要的并发瓶颈,因为每次分配都涉及获取保护该字段的锁.为避免此问题,大多数 JVM 使用线程本地分配块,其中每个线程从堆中分配更大的内存块,并从该线程本地块中按顺序为小型分配请求提供服务.因此,线程必须获取共享堆锁的次数大大减少,提高了并发性.

If the allocator were truly implemented as shown in Listing 1, the shared heapStart field would quickly become a significant concurrency bottleneck, as every allocation would involve acquiring the lock that guards this field. To avoid this problem, most JVMs use thread-local allocation blocks, where each thread allocates a larger chunk of memory from the heap and services small allocation requests sequentially out of that thread-local block. As a result, the number of times a thread has to acquire the shared heap lock is greatly reduced, improving concurrency.

* - JVM 优化可能允许某些对象成为 在栈上分配.

* - it's possible that JVM optimizations allow some objects to be allocated on the stack.

相关文章