AtomicInteger对应的方法如下:
调用了C++的如下代码
这里看到有一个LOCK_IF_MP,作用是如果是多处理器,在指令前加上LOCK前缀,因为在单处理器中,是不会存在缓存不一致的问题的,所有线程都在一个CPU上跑,使用同一个缓存区,也就不存在本地内存与主内存不一致的问题,不会造成可见性问题。然而在多核处理器中,共享内存需要从写缓存中刷新到主内存中去,并遵循缓存一致性协议通知其他处理器更新缓存。
Lock在这里的作用:
在cmpxchg执行期间,锁住内存地址[edx],其他处理器不能访问该内存,保证原子性。即使是在32位机器上修改64位的内存也可以保证原子性。
将本处理器上写缓存全部强制写回主存中去,也就是写屏障,保证每个线程的本地内存与主存一致。
禁止cmpxchg与前后任何指令重排序,防止指令重排序。
Java对象头:
在Hotspot虚拟机中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充();Java对象头是实现synchronized的锁对象的基础,一般而言,synchronized使用的锁对象是存储在Java对象头里。它是轻量级锁和偏向锁的关键.
import org.openjdk.jol.info.ClassLayout;
public class test001 {
public static void main(String[] args) {
Object demo = new Object();
System.out.println(ClassLayout.parseInstance(demo).toPrintable());
synchronized (demo) {
System.out.println(ClassLayout.parseInstance(demo).toPrintable());
}
}
}
可以看到加锁后除了Mawrk Word中不同,其他的都是相同的
某个应用程序过分的访问这些硬盘,内存等资源,就会导致整个系统的资源被占用,如果不对这种行为进行限制和区分,就会导致资源访问的冲突。所以,Linux的设计的初衷:给不同的操作给与不同的“权限”。Linux操作系统就将权限等级分为了2个等级,分别就是内核态和用户态
锁升级的过程:
级别由低到高依次为:无锁、偏向锁、轻量级锁、重量级锁
偏向锁:把自己的线程Id放到对象的Mawrk Word中
之前从轻量级锁(自旋锁)升级到重量有两个条件:
1.自旋次数>10,2.自旋的线程>cpu的一半
现在是JVM来决定自旋几次升级
重量级锁是指当有一个线程获取锁之后,其余所有等待获取该锁的线程都会处于阻塞状态。
简言之,就是所有的控制权都交给了操作系统,由操作系统来负责线程间的调度和线程的状态变更。而这样会出现频繁地对线程运行状态的切换,线程的挂起和唤醒,从而消耗大量的系统资