java 多线程-synchronized (一)
1:锁升级到的过程
首先要了解2个概念
- 什么是cas
- 对象在内存中的布局
1.1:CAS(compare and swap):自旋锁

这个过程中存在ABA问题:
- 进程P1在共享变量中读到值为A
- P1被抢占了,进程P2执行
- P2把共享变量里的值从A改成了B,再改回到A,此时被P1抢占。
- P1回来看到共享变量里的值没有被改变,于是继续执行。但实际过程中A数据已经被P2线程修改过,
- 虽然共享变量没改变,但是实际过程中是有修改动作 我们没法知道数据的修改历史
解决方案: 添加版本或者时间戳
1.2:java 对象+在内存中的布局

普通对象在内存中分为4块内容
- markword 标记位
- 类型指针 class pinter 哪个类,如果是student类这个就是student.class
- 实例数据,对象里面的成员变量
- 对齐位 前面字节不能被8整除,补齐,jvm 以安块来读取的
例如以下代码
Object o = new Object();
String s = ClassLayout.parseInstance(o).toPrintable();

- 图(1) 8个字节就是是markword
- 图(2) 4就是class pinter
- 补齐位,前面12个字节,后面补齐4位
知道对象布局后,我们再看是怎么上锁
//无锁
Object o = new Object();
String s = ClassLayout.parseInstance(o).toPrintable();
System.out.print(s);
//给对象上锁,就是对象头markword发生变化,
synchronized (o){
System.out.print(ClassLayout.parseInstance(o).toPrintable());

通过图片里面数据对比,所谓的加锁, 就是修改对象的头部 就是markword 的状态,我们观察对象的锁的升级过程,就是看markword的变化
上图红色划线的地方就是锁标志位(根据下午,我们可以根据markword 的参数值,来了解当前对象现在是否上锁)

锁的状态分为 无锁,偏向锁,轻量级锁,重量级锁
1.3锁的升级过程

刚实例对象的时候,我们有
打个比方
假设只有一台电脑,
1: 张三要用,只有张三一个人是的时候,直接在门上写着张三在使用,记录下id(线程id 记录到markword 里面)
2:现在李四也要使用这台电脑,现在就要开始竞争了,谁能够把自己信息贴到这个门上(),谁就能用这把锁(轻量锁)
3:如果人特别多,1000个人竞争,只有1个人在使用,还有99个在自旋,这个适合就需要惊动管理员(操作系统),来维护次序, 这个时候就需要升级到重量级锁(提供队列,wait set)
注升级重量级锁:
jdk1.6之前
某个线程自旋次数超过10次
等待自旋线程超过cpu 核素1/2 比如cpu 8核,5个线程就升级
jdk1.6以后 根据线程情况,判断是否需要升级(自适应自旋)
参考地址: https://www.cnblogs.com/cxiaocai/p/12189848.html

浙公网安备 33010602011771号