JAVA线程(不同堆栈)同步
对于由多个线程执行的代码的同步,我有一个问题: 据我所知,每个线程都有自己的堆栈,因此,非静态变量存在于每个线程内存中的不同位置(对于X个线程,有X个堆栈包含所有非静态变量)。 那么为什么需要同步任何东西呢JAVA线程(不同堆栈)同步,java,multithreading,synchronization,thread-safety,stack,Java,Multithreading,Synchronization,Thread Safety,Stack,对于由多个线程执行的代码的同步,我有一个问题: 据我所知,每个线程都有自己的堆栈,因此,非静态变量存在于每个线程内存中的不同位置(对于X个线程,有X个堆栈包含所有非静态变量)。 那么为什么需要同步任何东西呢 我的意思是,如果线程执行的代码包含一些类变量v1,那么每个线程都有自己的v1“实例”(不同的内存地址),没有其他线程可以“接触”它。。。不是吗?只有原语类型,例如int,才能保证在堆栈上分配。对象和数组通常都存储在堆中,除非确定对象的范围“限制在过程的范围内”。堆栈是(考虑调用堆栈、局部变量
我的意思是,如果线程执行的代码包含一些类变量v1,那么每个线程都有自己的v1“实例”(不同的内存地址),没有其他线程可以“接触”它。。。不是吗?只有原语类型,例如
int
,才能保证在堆栈上分配。对象和数组通常都存储在堆中,除非确定对象的范围“限制在过程的范围内”。堆栈是(考虑调用堆栈、局部变量),但类变量位于堆中,您必须同步对它们的访问:)在同一个对象实例上,如果您的方法未同步,则无法保证同一代码不会在不同线程中执行两次-->浩劫!哪个是正确的值
至少,您希望将访问变量的方法声明为已同步。如果您想要更细粒度的控制,您可以使用,例如,ReentrantReadWriteLock
声明同步的方法会在对象实例上同步,因此这是安全的。局部变量、原语和引用隐式地是线程局部的。但是,引用的对象可以共享,当线程可以修改共享对象时,很可能需要同步、锁定或其他策略来确保线程安全。除非同步代码,否则堆栈是线程安全的,而堆不是线程安全的。堆栈包含局部变量和方法参数(原语和引用),而堆包含对象
对于每个线程,非静态变量存在于内存中的不同位置 这不是真的,所以答案是 如果线程执行的代码包含一些类变量v1,那么每个线程都有自己的v1“实例”(不同的内存地址),没有其他线程可以“接触”它。。。不是吗 是否。线程可以接触由其他线程分配和修改的对象实例,程序员的责任是确保这不会影响程序的正确性 类成员变量存在于每个类实例的内存中的单个位置,而不是每个线程。的确,在这两者之间(想想
synchronized
的开始{
和结束}
),线程可能有对象状态的缓存,但这与每个线程存储的语言要求不同。“每个线程的内存”是它的堆栈,它不包含对象成员*——只引用对象
最好的想法是,堆上每个对象都有一个位置,但可能同时发生多个涉及该内存位置的读写操作
如果您听说线程在堆的不同部分分配对象,我可以看出您是如何得出结论的。一些JVM有一个优化,通过这个优化,它们可以执行,但不会阻止其他线程访问这些对象
线程本地分配
如果分配器真的如清单1所示实现,那么共享heapStart字段将很快成为一个重要的并发瓶颈,因为每次分配都需要获取保护该字段的锁。为了避免这个问题,大多数JVM使用线程本地分配块,其中每个线程从堆中分配一个较大的内存块,并从该线程本地块中按顺序为小的分配请求提供服务。因此,线程获取共享堆锁的次数大大减少,从而提高了并发性
*-JVM优化可能允许对某些对象进行优化。一些关键点有助于澄清您的疑问-
Nrj的想法是正确的。事实上,语言规范没有说明在哪里分配对象,现代JVM在堆栈上分配对象方面做得很好,如果可以的话。我的意思是在Java VM
概念性的
堆栈上,在分配行为等方面。如果对象“永不逃避它的基本块”。但我不介意修改我的答案,以更好地反映detailAfaik Hotspot确实在堆栈上分配对象,如果它能证明明显的条件(即仅限于局部对象,这在某些EA中很容易保证)@Voo,我找到了一些对堆栈分配的引用,并编辑了我的括号以添加链接。(1)不正确(寻找转义分析);(2)没有太多意义(“同一对象的线程”?!);(3)这很明显,不是吗?我的意思是,如果某个东西不是“否”