CAS操作、Java对象头、偏向锁的获取与撤销、轻量级锁的获取与撤销、锁粗化、锁消除


Synchronized优化:
  在JDK 1.5中,synchronized的性能是很低的,因为这是一个重量级的操作,它对性能最大的影响是阻塞的实现、挂起线程、和恢复线程都需要转入内核态完成,这些给操作系统的并发性带来了很大的压力。
  但是在JDK1.6,发生了变化,对synchronized加入了很多优化措施,
  之前我们已经对synchronized有一定的了解,它最大的特征就是在同一时刻只有一个线程能够获得对象的监视器(monitor),从而2进入到同步代码块或者同步方法中,即表现为互斥性(排它性)。这种方式效率低下,每次只能通过一个线程,既然每次都只能通过一个,如果这种形式不能改变的话,那么我们能不能让每次通过的速度变快一点呢?
  比如:去收银台付款,之前的方式是大家都去排队,然后取纸币付款收银员找零,付款的时候需要在包里拿出钱包再拿出钱,这个过程是比较耗时的,然后支付宝解放了大家去钱包找钱的过程,现在只需要扫描二维码就可以完成付款,也省去了收银员找零的时间,同样是需要排队付款,但整个付款的时间大大缩短,整体效率也变快了。这种优化同样可以引申到锁优化上,缩短获取锁的时间。
在锁优化之前,需要关注两个知识点(1)CAS操作 (2)Java对象头

1. CAS操作

1.1 什么是CAS?

  在使用锁时,线程获取锁是一种悲观锁策略,即假设每一次执行临界区代码都会产生冲突,所以当前线程获取到锁的时候同时也会阻塞其他线程获取该锁。而CAS操作是一种乐观锁策略,它假设所有线程访问共享资源的时候不会出现冲突,既然不会出现冲突自然而然就不会阻塞其他线程的操作。因此,线程就不会出现阻塞停顿的状态,那么这种情况下出现冲突了怎么办?无锁操作是使用CAS(compare and swap)又叫做比较交换来鉴别线程是否出现冲突,出现冲突就重试当前操作直到没有冲突为止。

1.1.1 CAS的操作过程

CAS可以通俗的理解为CAS(V,O,N)其中包含三个值分别是
V:内存地址中实际存放的值;
O:预期的值;
N:更新后的值。

  当V==O相同时,也就是说预期值和内存中实际的值相同,表明该值没有被其他线程更改过,即预期值O就是目前来说最新的值了,可以将N赋给V。
  当V!=O不相同,表明V值已经被其他线程改过了,即预期值0不是最新值了,所以不能将新值N赋给V,返回V值,将O值改为V。

  当多个线程使用CAS操作一个变量时,只有一个线程会成功并成功更新,其余会失败,失败的线程会重新尝试(自旋),当然也可以选择挂起线程(阻塞)。

未优化的synchronized最主要的问题是:
   在存在线程竞争的情况下会出现线程阻塞和唤醒锁带来的性能问题,这是一种互斥同步(阻塞同步)
  而CAS并不是武断的将线程挂起,当CAS操作失败后会进行一定的尝试,而非进行耗时的挂起唤醒的操作,因此也叫做非阻塞同步。

1.1.2 CAS带来的问题

1.1.2.1 CAS带来的ABA问题

  线程1准备用CAS将变量的值由A替换为B,在此之前,线程2将变量的值由A替换为C,又由C替换为A,然后线程1执行CAS时发现变量的值仍然为A,所以CAS成功。但实际上这时的现场已经和最初不同了。
  例如一个单向链表:

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值