对线程中锁的理解

对线程中锁的理解
在并发编程时,我们经常会遇到多个线程访问同一个共享变量,当同时对该共享变量做读写操作时,就会产生数据不一致的问题。基于这个场景,我们要讨论的内容– 产生了。
首先引发一个问题。锁是什么
锁,是一种线程中的一种同步机制。通过加锁,可以实现对共享资源的互斥访问。
锁有哪些
根据不同维度,有不同类型的锁。但深究下来,其实也就是由如下两种情况产生。
. 使用synchronized关键字修饰成员变量、代码块、方法产生的锁。
. 并发工具包java.util.concurrent.lock包下的一些实现了Lock接口的类,常见的诸如可重入锁RetrantLock,可重复读写锁RetrantReadWriteLock。
可重入锁
**.**指在同一个线程中,在外层方法获取锁的时候,进入内层方法会自动获取锁。为避免死锁的产生,JDK中基本都是可重入锁。
公平锁 / 非公平锁
**.**公平锁,指多个线程按照申请锁的顺序获取锁。
如java.util.concurrent.lock.RetrantLock.FairSync
**.**非公平锁,指多个线程获取锁的顺序并不按照申请锁的顺序,有可能后申请的线程先获得锁。如synchronized,java.util.concurrent.lock.RetrantLock.NonfairSync。
悲观锁 / 乐观锁
. 悲观锁,总是考虑最坏的情况,每次操作数据的时候,认为数据一定会被其他线程修改。
. 适用场景:写操作比较多,先加锁可以保证写操作时数据的正确性。
. 悲观锁的实现有如下方式
. Java代码层面,使用synchronized关键字,接口Lock的实现类,如RetrantLock。
. MySQL中的行锁、表锁、读锁、写锁或诸如select…for update
. 乐观锁,表现的很乐观,认为数据不会被其他线程修改。所以不会一开始就加锁,只有在更新的时候会判断该数据是否被修改。
**.**适用场景:读多写少。可提高吞吐量
乐观锁有如下方式实现
. java代码中的automic包下的类如AutomicInteger或通过CAS算法实现。
. 数据库层面给数据库表添加一个数字类型的“version”字段或者添加一个timestamp时间戳类型的字段。
独占锁 / 共享锁
**.**独占锁,指锁一次只能被一个线程所持有。
synchronized、java.util.concurrent.lock.RetrantLock都是独占锁。
. 共享锁,指锁可被多个线程所持有。
ReadWriteLock返回的ReadLock就是共享锁
自旋锁
. 指尝试获取锁的线程不会立即阻塞,二十采用循环的方式去尝试获取锁。
. 作用:自旋锁可减少线程上下文切换的消耗。
. 缺点:循环占有,浪费CPU资源。

偏向锁 / 轻量级锁 / 重量级锁
严格上来所,这几个锁是对关键字synchronized的加锁的状态升级的描述。
通过synchronized加锁后,锁会有如下变化。
**.**偏向锁,一段同步代码一直被同一个线程访问,那么该线程获取的就是偏向锁。
**.**轻量级锁, 偏向锁被一个其他线程访问,java对象的偏向锁就会升级为轻量级锁。
. 重量级锁,其他线程以自旋的方式尝试获取锁,不会发生阻塞,自旋到一定次数仍未获取到锁,轻量级锁就会升级为重量级锁。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐先生Paul

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值