java的锁介绍(乐观锁与悲观锁)

2019第一篇文章-java的锁介绍(乐观锁与悲观锁)

什么是乐观锁、悲观锁

第一次听到这个名字,怎么把锁都拟人化了?所以很好奇的去查阅了下,看了之后,发现这样比喻确实有它的道理。对应到代码来说,就简单了。锁是java并发处理的一种实现方式,那我们来了解下这两种锁。
乐观锁,总是很乐观的,在多线程并发过程中,不会认为别人每次会修改自己的数据,所以再别人操作时候不会上锁,如果是读取数据,那么直接返回数据,如果是更新数据,那么做一次判断,是否有别人更新,等待别人更新后再更新。那么这个很明显的优势就是,性能较高,不会因为每次上锁而降低性能,应用于高吞吐的操作。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS(compare and set)实现的。AtomicBoolean(用原子方式更新的boolean值)、AtomicInteger(用原子方式更新的int值)和AtomicLong(用原子方式更新的long值)
悲观锁,总是很悲观的,在多线程并发过程中,总是认为别人会侵犯自己,比如别人来读取或者修改数据,都会先上锁,当处理完成后再释放锁。如果是写,倒是还好,如果只是读取呢?那么势必会减低读取性能。这种锁独自占用资源,也叫做独占锁,在java中,使用关键字synchronized表示或者lock的就是这个类型。

乐观锁的CAS实现

CAS是乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。CAS是非阻塞算法。
以 java.util.concurrent 中的 AtomicInteger 为例,该类中原子操作保证了线程访问的准确性。
getAndIncrement():获取数据
compareAndSet(int expect, int update): 更新数据
利用JNI(Java Native Interface)来完成CPU指令的操作,访问寄存器内存数据进行数据访问和设置。

使用选择

CAS与Synchronized的使用情景:

1、对于资源竞争较少(线程冲突较轻)的情况,使用synchronized同步锁进行线程阻塞和唤醒切换以及用户态内核态间的切换操作额外浪费消耗cpu资源;而CAS基于硬件实现,不需要进入内核,不需要切换线程,操作自旋几率较少,因此可以获得更高的性能。

2、对于资源竞争严重(线程冲突严重)的情况,CAS自旋的概率会比较大,从而浪费更多的CPU资源,效率低于synchronized。

补充: synchronized在jdk1.6之后,已经改进优化。synchronized的底层实现主要依靠Lock-Free的队列,基本思路是自旋后阻塞,竞争切换后继续竞争锁,稍微牺牲了公平性,但获得了高吞吐量。在线程冲突较少的情况下,可以获得和CAS类似的性能;而线程冲突严重的情况下,性能远高于CAS。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值