JAVA线程(不同堆栈)同步

JAVA线程(不同堆栈)同步,java,multithreading,synchronization,thread-safety,stack,Java,Multithreading,Synchronization,Thread Safety,Stack,对于由多个线程执行的代码的同步,我有一个问题: 据我所知,每个线程都有自己的堆栈,因此,非静态变量存在于每个线程内存中的不同位置(对于X个线程,有X个堆栈包含所有非静态变量)。 那么为什么需要同步任何东西呢 我的意思是,如果线程执行的代码包含一些类变量v1,那么每个线程都有自己的v1“实例”(不同的内存地址),没有其他线程可以“接触”它。。。不是吗?只有原语类型,例如int,才能保证在堆栈上分配。对象和数组通常都存储在堆中,除非确定对象的范围“限制在过程的范围内”。堆栈是(考虑调用堆栈、局部变量

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

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


我的意思是,如果线程执行的代码包含一些类变量v1,那么每个线程都有自己的v1“实例”(不同的内存地址),没有其他线程可以“接触”它。。。不是吗?

只有原语类型,例如
int
,才能保证在堆栈上分配。对象和数组通常都存储在堆中,除非确定对象的范围“限制在过程的范围内”。

堆栈是(考虑调用堆栈、局部变量),但类变量位于堆中,您必须同步对它们的访问:)

在同一个对象实例上,如果您的方法未同步,则无法保证同一代码不会在不同线程中执行两次-->浩劫!哪个是正确的值

至少,您希望将访问变量的方法声明为已同步。如果您想要更细粒度的控制,您可以使用,例如,
ReentrantReadWriteLock


声明同步的方法会在对象实例上同步,因此这是安全的。

局部变量、原语和引用隐式地是线程局部的。但是,引用的对象可以共享,当线程可以修改共享对象时,很可能需要同步、锁定或其他策略来确保线程安全。

除非同步代码,否则堆栈是线程安全的,而堆不是线程安全的。堆栈包含局部变量和方法参数(原语和引用),而堆包含对象


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

这不是真的,所以答案是

如果线程执行的代码包含一些类变量v1,那么每个线程都有自己的v1“实例”(不同的内存地址),没有其他线程可以“接触”它。。。不是吗

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

类成员变量存在于每个类实例的内存中的单个位置,而不是每个线程。的确,在这两者之间(想想
synchronized
的开始
{
和结束
}
),线程可能有对象状态的缓存,但这与每个线程存储的语言要求不同。“每个线程的内存”是它的堆栈,它不包含对象成员*——只引用对象

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

如果您听说线程在堆的不同部分分配对象,我可以看出您是如何得出结论的。一些JVM有一个优化,通过这个优化,它们可以执行,但不会阻止其他线程访问这些对象

线程本地分配

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


*-JVM优化可能允许对某些对象进行优化。

一些关键点有助于澄清您的疑问-

  • 对象总是在堆上分配的

  • 类级变量跨线程共享(同一对象的线程)

  • 局部变量始终是线程安全的(如果没有以非线程安全的方式暴露于外部世界)

  • “非静态变量存在于不同位置”可能不正确。在Java中,您永远不会直接了解“堆栈”的任何内容。所有的类变量,静态或实例,都来自堆。但是,作为java开发人员,您并不真正关心这一点

    你唯一不关心线程安全的时候是当你的类是不可变的(构造后不要改变)或者你从来没有在线程中做过任何事情。如果您的类不属于这两类,您需要考虑使它们成为线程安全的

    设计中的不变性越多,线程问题就越容易推理和克服


    Nrj的想法是正确的。

    事实上,语言规范没有说明在哪里分配对象,现代JVM在堆栈上分配对象方面做得很好,如果可以的话。我的意思是在Java VM
    概念性的
    堆栈上,在分配行为等方面。如果对象“永不逃避它的基本块”。但我不介意修改我的答案,以更好地反映detailAfaik Hotspot确实在堆栈上分配对象,如果它能证明明显的条件(即仅限于局部对象,这在某些EA中很容易保证)@Voo,我找到了一些对堆栈分配的引用,并编辑了我的括号以添加链接。(1)不正确(寻找转义分析);(2)没有太多意义(“同一对象的线程”?!);(3)这很明显,不是吗?我的意思是,如果某个东西不是“否”