Java 原子操作的原理和问题

来源:互联网 发布:淘宝人生txt下载 编辑:程序博客网 时间:2024/06/05 05:33

对java并发机制的底层实现原理学习了一下,有一些浅薄的收益。

第一了解的是:java对象在JVM中有一个java对象头的概念,synchronized用的锁的信息就是存在java对象头里面,根据其中存储的markword的线程是否指向自己的线程来判断是否持有当前锁。

java对象头的长度视图:


32位的对象头的mark word存储结构的视图:


64位的对象头的mark word存储结构的视图:



我们知道java se1.6之后,引入了偏向锁和轻量级锁的概念,锁一共有4种状态:无锁状态,偏向锁状态,轻量级锁状态和重量级锁状态。

所以在不同锁的时候。java对象头中markword是不一样的。

具体事例如下图:



第二是原子操作的实现原理:

两个概念,1,原子操作:原子操作就是在计算机这个世界中,能够做的最小的操作了。然而这些操作基本都基于一个叫做CAS(compare and swap)的操作,

2:缓存行:缓存的最小单位。(cache line)


抛出问题:如果两个线程对int i=1;进行i++;的操作,我们实际期望的结果是3,但是很可能出现的结果是2.

处理器保证内存操作的原子性是基于两个机制的。

第一:通过总线程锁保证原子性。所谓总线程锁就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住。那么该处理器可以独占共享内存。(缺点:总线程锁把CPU和内存之间的通信锁住了,这使得锁定期间,其他处理器不能操作其他内存地址的数据,所以总线锁定的开销较大。)

第二:频繁使用的内存会缓存在处理器的L1,L2和L3高速缓存里,那么原子操作就可以直接再处理器内部缓存中进行,并不需要声明总线程锁。可以通过缓存锁来保证原子性。所谓缓存锁是指内存区域如果被缓存在处理器的缓存行中,并且在Lock操作期间被锁定,那么当它执行锁操作回写到内存时,处理器不在主线上声言Lock#信号,而是修改内部的内存地址,并允许它的缓存一致性机制来保证操作的原子性,因为缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据,当其他处理器回写已被锁定的缓存行的数据时,会使缓存失效。




0 0