堆内存分配的并发问题
在实际的开发过程中,会经常的创建对象,作为虚拟机,必须保证线程安全。通常来讲虚拟机采用两种方式保证线程安全
一、CAS + 失败重试
CAS是一种乐观锁的实现方式,每次不加锁假设没有冲突的去完成某项操作,如果因为冲突导致操作失败就重试,直到成功为止。详见博客,传送地址:Java并发编程之 无锁(CAS)
二、TLAB
TLAB是在Java堆空间的伊甸园划分出来的针对每个线程的内存空间,专门在该区域为该线程创建的对象分配内存。
它的主要目的是在并发环境下进行内存分配的时候,减少线程之间对于内存空间的竞争,加速内存分配的速度。
TLAB本质上还是在Java堆中的,所以在TLAB区域的对象,也可以被其他线程访问。
如果没有使用TLAB,多个并发执行的线程创建对象,分配内存的时候,有可能在Java堆中的同一个位置申请,这就需要对这部分内存空间进行加锁或者采用CAS等操作保证线程安全,即保证该区域只分配给一个线程。
使用了TLAB之后,JVM会针对每个线程在堆内存中预留一个内存区域,在预留这个操作发生的时候,需要进行加锁或者采用CAS等操作进行保护,避免多个线程预留同一个区域。一旦确定了某个区域分配给某个线程,之后该线程需要分配内存的时候,会优先在这片区域申请。这个区域对于该线程分配内存这个操作而言是线程私有的,因此在分配的时候不用进行加锁等操作,从而既保护了线程安全又提升了分配速度。
注意: 当该线程创建的对象大于TLAB中的剩余内存或者TLAB的内存已用尽时,再采用CAS + 失败重试的方式分配内存。
还没有评论,来说两句吧...