ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

常见的锁策略

2021-10-17 15:00:25  阅读:128  来源: 互联网

标签:重入 加锁 策略 Synchronized 常见 互斥 线程 CPU


常见的锁策略

乐观锁与悲观锁

乐观锁:既假设锁冲突的概率比较低基本没有冲突,简单的处理冲突。
悲观锁:既假设锁冲突的概率比较高基本每次尝试加锁都会产生锁冲突,付出更多的成本处理冲突。
Synchronized初始使用乐观锁策略。当发现锁竞争比较频繁的时候就会自动切换成悲观锁策略。
乐观锁的一个重要功能就是检测数据是否发生冲突。引入“版本号”解决。
如修改账户余额:提交版本号必须大于记录当前版本号才能执行更新
在这里插入图片描述

读写锁

线程对于数据的访问,主要存在两种操作:读操作和写操作。

  • 两个读线程之间,其实不存在线程安全,就不必互斥。
  • 两个写线程之间,存在线程安全,需要互斥。
  • 一个读线程一个写线程,存在线程安全,就需要互斥。

在有些场景中,本来就写比较少,读比较多。
Synchronized并没有对读写进行区分,只要使用就一定互斥,像这种读比较多写比较少的情景效率就比较低。此时就需要读写锁。
Java标准库里就提供了这个类:

  • ReentrantReadWriteLock.ReadLock能够构造一个读锁实例,提供了lock/unlock方法进行加锁解锁.
  • ReentrantReadWriteLock.WriteLock能够构造一个写锁实例,提供 lock/unlock方法进行加速解锁.

假设有t1 t2两个读线程,t3 t4两个写线程。使用ReentrantReadWriteLock.ReadLock和
ReentrantReadWriteLock.WriteLock这两个类来进行加锁。

  • t1和t2两个读线程同时访问数据,此时两个读锁之间不会互斥,完全并发执行。
  • t1和t3一个读线程一个写线程同时访问数据,此时读锁和写锁之间就会互斥。要么读完再写,要么写完再读
  • t3和t4两个写线程同时访问,此时写锁和写锁之间会互斥,一定是一个线程写完另一个线程再写。

Synchronized不是读写锁

重量级锁与轻量级锁

首先我们需要知道锁的核心特征“原子性”,这样的机制是CPU这样的硬件设备提供的。

  • CPU提供“原子操作指令”
  • 操作系统基于CPU的原子指令实现mutex互斥锁
  • JVM基于操作系统提供的互斥锁,实现了Synchronized和ReentrantLock等关键字和类。

重量级锁:加锁机制依赖操作系统提供的mutex。

  • 大量的内核态用户态切换
  • 很容易引发线程调度

轻量级锁:加锁机制很少使用mutex而是尽量在用户态代码完成。

  • 少量的内核态用户态切换
  • 不太容易引发线程调度

Synchronized开始是一个轻量级锁。如果锁冲突比较严重就会变成重量级锁。

自旋锁与挂起等待锁

自旋锁:如果线程获取不到锁,不是阻塞等待而是循环的快速的再试一次,因此就节省了操作系统调度线程的开销,比挂起等待锁更能及时的获取到锁。但是更浪费CPU资源。
挂起等待锁:如果线程获取不到锁,就会阻塞等待,什么时候结束阻塞,取决于操作系统的调度。当线程挂起的时候不占用CPU。
使用自旋锁与挂起等待锁的大原则:

  • 如果锁冲突的概率比较低,使用自旋锁比挂起等待锁更合适。
  • 如果线程持有锁的时间比较短,使用自旋锁比挂起等待锁更合适。
  • 如果对CPU比较敏感,比希望吃太多CPU资源就适合使用挂起等待锁。

Synchronized根据情景在自旋锁和挂起等待锁之间转换。

公平锁与非公平锁

公平锁:遵循“先来后到”如张三比李四先喜欢女神,此时如果女神分手就会先考虑与张三在一起。
非公平锁:不遵循“先来后到”如张三比李四先喜欢女神,此时如果女神分手女神会选择一个看着比较顺眼的,不按照先后顺序选择。
操作系统内部的线程调度默认是不公平的,随机的。如果要实现公平锁,就需要依赖额外的数据结果(如队列,通过队列来记录先来后到的过程),来记录线程的先后顺序。
Synchronized是非公平锁

可重入锁与不可重入锁

可重入锁:允许同一个线程多次获取同一把锁。
实现方式:在锁中记录锁持有的线程身份,以及一个计数器。如果发现,当前有同一个线程尝试获取锁,这个时候不会阻塞等待而是继续运行,每次加锁记数器++,每次解锁,计数器–,直到计数器为0,此时才是真正的释放锁,其他线程才能获取到这个锁。
不可重入锁:同一个线程只能获取一把锁,如果多次获取锁会出现死锁情况。
Synchronized是可重入锁

标签:重入,加锁,策略,Synchronized,常见,互斥,线程,CPU
来源: https://blog.csdn.net/weixin_50910403/article/details/120802106

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有