申明:本片文章是自己学习的理解,本人暂时只是入门,有很多知识都需要完善,可能这个文章现在只有我自己能够看懂,见谅。
更新:2020-7-9
并发并行
并发:一个处理器同时处理多个任务
并行:多个处理器或者多核的的处理器处理多个问题
CAS (Compare And Exchang)
CAS 在没有锁、多线程的状态下,可以保证对一个值的更新。(记住这个特点)
CAS的过程:
在不加锁,多线程中,假设有个变量var
,
1、首先读取var变量的值,假设读取到的var值为0
2、执行计算操作,这个假设执行操作为var++
3、判断var的值是否是刚开始读到的值0,如果值为0,就将计算后的var值赋值给var,如果读到的var值不是刚开始读到的var值,他就会更新这个var的值,然后执行var++,相当与开始重复步骤一了,直到将操作后的值写入到var变量中
CAS的应用
你可能听说过原子类,比如说AtomicInteger,它就是用了CAS,往下看:
// 这里定义了一个 AtomicInteger 的对象i
AtomicInteger i = new AtomicInteger()
// AtomicInteger有个方法 incrementAndGet()
i.incrementAndGet()
AtomicInteger.java
//将入 AtomicInteger.java 的源码,可以看到incrementAndGet的实现方法,这里返回了一个unsafe.getAndAddInt()
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
Unsafe.class
// 进入Unsafe.class,就可以看到CAS的使用
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
ABA
ABA问题,简单来说就是,你在给一个变量写入数据还没有写入的时候,有一个线程来读取了这个变量的值。
解决ABA问题的方法,就是加一个版本号的标识符,在读取值的时候,将版本号一并读取(或者是加布尔值)
lock cmpxchy 指令
JOL(Java Object Layout)
JOL,中文翻译:java对象布局
可以看一下上面的图,对象在内存中的存储对象
1、markword,对象头的一部分,关于锁的信息,关于Synchronized的信息都在这里面
2、class point,类型指针,说明是属于什么类的
3、instance data 实例数据,就是你的成员变量待得地方
4、padding 对齐,就是所有的字节加起来,不能够被8整除,就给补,补成能够被8整除
–
对象头是markword 和 class point两部分组成的
问:对象在内存中占多少个字节
回答这个问题需要一个概念就是,
JVM中默认开启了UseCompressedClassPointers,意思就是字节压缩,在java 虚拟机HotSpot,是64位的,8字节,但是有UserCompressedClassPointers,会将8字节压缩成4字节。
(这里考虑的是在没有成员变量的时候,下面类似)
开启压缩
markword 8 字节
class pointer 4字节 上面解释了class pointer 为什么是4字节
instance data 0字节,因为Object 没有实例对象,所有为0
padding 4字节,前面不能够被 8整除
不开启压缩
markword 8 字节
class pointer 8字节
instance data 0 字节
padding 0字节
这里给出java中常用的基本类型的字节数
1、整型
int 4字节
short 2字节
long 8字节
byte 1字节
2、浮点型
float 4字节
double 8字节
3、char类型
char 2字节
4、Boolean
boolean 1字节
问:String 是基本数据类型嘛?
String不是基本数据类型,而是一个类,是java编程语言中的字符串。String对象是char的有序集合,并且该值是不可变的。
Synchronized
···java
Synchronized(0){
// 执行代码
}
执行这段代码,给这个对象上锁
锁升级
markword 8 字节一共64位。
所升级过程