锁——待优化

用户态和内核态

cas
compare and swap
compare and exchange
CAS(比较并交换)是CPU指令级的操作,只有一步原子操作,所以非常快。而且CAS避免了请求操作系统来裁定锁的问题,不用麻烦操作系统,直接在CPU内部就搞定了。

重量级锁(创建锁需要惊动操作系统————0x80中断)

锁的升级

无锁态-偏向锁-自旋锁-重量级锁

偏向锁:只有一个线程使用,没有其他线程竞争,使用线程贴个标签标识该资源正在被使用

自旋锁:轻度竞争,一个线程在使用,其他少量线程等待资源,但拿不到资源,所以不停询问可以用了吗,ha所以叫自旋锁。(自旋锁是一种乐观锁。);等待自旋锁的线程不会释放CPU资源,占用cpu做无用功。

重量级锁:最常见的是synchronize,重度竞争,等待的线程多,占用时间长,这种情况下,等待线程释放cpu资源,进入等待池,效率更高。

自旋锁的优势是轻度竞争条件下,避免操作系统层面申请锁,来提升效率,达到这个目的的方法就是等待线程不释放,一直询问。如果出现重度竞争的情况,还不如释放资源,申请os级的锁更快。

偏向锁一定更快吗?

jol(java object layout)

mark word
class pointer 属于哪个类
instance data 成员变量
padding 被8整除,否则补齐

mark word的3个作用:
锁、GC、hashcode

volatile  线程读取某个变量时,不会在线程缓存创建这个变量的备份,而是直接从内存中读取。volatile适合一个线程写,多个线程读的场景。

volatile还能禁止指令重排序。

对象的创建过程:

汇编码:

0  new #2 <T>  向内存申请空间,成员变量为默认值

1  dup

2  invokespecial #3 <T.<init>>  T的构造方法,初始化成员变量

3  astore1  与类建立关联

4  return

单例为什么可不可以用volatile。

class T{

  private static volatile T(){}

}

半初始化状态,如果线程1调用单例,创建对象,执行了0,然后指令重排序,执行了3,没执行2,此时对象不为空,但是成员变量还是默认值,然后另一个线程也调用单例,将拿到半初始化的对象(对象不为空,但成员变量还没有初始化)。

猜你喜欢

转载自www.cnblogs.com/hellodingc/p/12907651.html