网站首页 > 精选教程 正文
自旋锁
当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。获取锁的线程一直处于活跃状态,但是并没有执行任何有效的任务,使用这种锁会造成busy-waiting。
优缺点
自旋锁不会使线程状态发生切换,一直处于用户态,即线程一直都是active的。不会使线程进入阻塞状态,减少了不必要的上下文切换,执行速度快非自旋锁在获取不到锁的时候会进入阻塞状态,从而进入内核态,当获取到锁的时候需要从内核态恢复,需要线程上下文切换。 (线程被阻塞后便进入内核(Linux)调度状态,这个会导致系统在用户态与内核态之间来回切换,严重影响锁的性能)
由于自旋锁只是将当前线程不停地执行循环体,不进行线程状态的改变,所以响应速度更快。但当线程数不停增加时,性能下降明显,因为每个线程都需要执行,占用CPU时间。
阻塞锁
在JAVA环境中,线程Thread有如下几个状态:
- 新建状态
- 就绪状态
- 运行状态
- 阻塞状态
- 死亡状态
阻塞锁让线程进入阻塞状态进行等待,当获得相应的信号(唤醒,时间) 时,才可以进入线程的准备就绪状态,准备就绪状态的所有线程,通过竞争,进入运行状态。JAVA中,能够进入 / 退出、阻塞状态或包含阻塞锁的方法有 ,synchronized 关键字(其中的重量锁),ReentrantLock,Object.wait() / notify() ,LockSupport.park() / unpart()
优缺点
阻塞的线程不会占用CPU时间, 不会导致 CPU占用率过高。进入时间以及恢复时间都要比自旋锁略慢。在竞争激烈的情况下,阻塞锁的性能要明显高于自旋锁。
在线程竞争不激烈的情况下,使用自旋锁;竞争激烈的情况下使用,阻塞锁
可重入锁
也叫递归锁,同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。 “独占”,就是在同一时刻只能有一个线程获取到锁,而其它获取锁的线程只能处于同步队列中等待,只有获取锁的线程释放了锁,后继的线程才能够获取锁。“可重入”,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁。
ReentrantLock 和synchronized 都是可重入锁。
Synchronized和ReentrantLock区别
1)性能:
在Synchronized优化以前,synchronized的性能是比ReenTrantLock差很多的,但是自从Synchronized引入了偏向锁,轻量级锁(自旋锁)后,两者的性能就差不多了,在两种方法都可用的情况下,官方甚至建议使用synchronized, synchronized的优化我感觉就借鉴了ReenTrantLock中的CAS技术。都是试图在用户态就把加锁问题解决,避免进入内核态的线程阻塞。
2)原理:
Synchronized: 进过编译,会在同步块的前后分别形成monitorenter和monitorexit这个两个字节码指令。在执行monitorenter指令时,首先要尝试获取对象锁。如果这个对象没被锁定,或者当前线程已经拥有了那个对象锁,把锁的计算器加1,相应的,在执行monitorexit指令时会将锁计算器就减1,当计算器为0时,锁就被释放了。如果获取对象锁失败,那当前线程就要阻塞,直到对象锁被另一个线程释放为止。
ReentrantLock: 是java.util.concurrent包下提供的一套互斥锁,相比Synchronized,ReentrantLock类提供了一些高级功能
等待可中断,持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待,这相当于Synchronized来说可以避免出现死锁的情况。通过lock.lockInterruptibly()来实现这个机制。
公平锁,多个线程等待同一个锁时,必须按照申请锁的时间顺序获得锁,Synchronized锁非公平锁,ReentrantLock默认的构造函数是创建的非公平锁,可以通过参数true设为公平锁,但公平锁表现的性能不是很好。
锁绑定多个条件,一个ReentrantLock对象可以同时绑定对个对象。ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。
读写锁
ReadWriteLock同Lock一样也是一个接口,提供了readLock和writeLock两种锁的操作机制,一个是只读的锁,一个是写锁。
读写锁比互斥锁允许对于共享数据更大程度的并发。与互斥锁相比,读写锁是否能够提高性能取决于读写数据的频率、读取和写入操作的持续时间、以及读线程和写线程之间的竞争。
- 读-读能共存,
- 读-写不能共存,
- 写-写不能共存。
锁降级
读写锁支持锁降级,遵循按照获取写锁,获取读锁再释放写锁的次序,写锁能够降级成为读锁,不支持锁升级
互斥锁
互斥是通过竞争对资源的独占使用,彼此之间不需要知道对方的存在,执行顺序是一个乱序。同步是协调多个相互关联线程合作完synchronized不同用法锁对象说明。
synchronized和Lock是互斥锁
修饰在静态方法上,锁对象是当前类的Class对象修饰在实例方法上,锁对象是当前实例对象同步块中,锁对象是synchronized括号后面的对象成任务,彼此之间知道对方存在,执行顺序往往是有序的。
悲观锁、乐观锁
悲观锁
假设会发生并发冲突,屏蔽一切可能违反数据完整性的操作(具有强烈的独占和排他性) 依赖数据库的锁机制实现,以保证操作最大程度的独占性。数据库性能的大量开销,特别是对长事务而言,这样的开销无法承受。sql后面加上 for update或者for update nowait。
独占锁是一种悲观锁,synchronized就是一种独占锁,它假设最坏的情况,并且只有在确保其它线程不会造成干扰的情况下执行,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。
乐观锁
假设不会发生并发冲突,只有在提交操作时检查是否违反数据完整性,乐观锁不能解决脏读问题
乐观锁大多都基于数据版本(version)记录机制实现,数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据表增加一个“version”字段来实现。读取出数据时,将此版本一同读出,之后更新时,对此版本后 +1。将提交的版本数据与数据库表对应记录的当前版本信息对比时,如果提交的数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据。
优缺点
可以多个事务同时进行,然后根据返回的不同结果做相应的操作,避免了长事务中的数据库加锁开销。
乐观锁机制往往基于系统中的数据存储逻辑,因此也具备一定的局限性。
公平锁、非公平锁
公平锁
加锁前先查看是否有排队等待的线程,有的话优先处理排在前面的线程,先来先得。
非公平锁
线程加锁时直接尝试获取锁,获取不到就自动到队尾等待。
非公平锁比公平锁性能高5-10倍,因为公平锁需要在多核情况下维护一个队列,如果当前线程不是队列的第一个无法获取锁,增加了线程切换次数。
- 上一篇: mysql的锁机制
- 下一篇: JAVA中有哪些锁?各种锁的实现方式?程序员面试如何回答?
猜你喜欢
- 2024-11-21 Java中的重重“锁”事
- 2024-11-21 线程进阶:多任务处理——Java中的锁(Unsafe基础)
- 2024-11-21 深入理解MySQL锁机制原理
- 2024-11-21 Java并发锁的原理,你所不知道的Java“锁”事
- 2024-11-21 阿里二面:你知道Java中的同步与锁机制详解?
- 2024-11-21 知识点深度解读系列-JAVA锁
- 2024-11-21 图解Java中的锁:什么是死锁?怎么排查死锁?怎么避免死锁?
- 2024-11-21 Java锁与线程的那些“不可描述”的事儿
- 2024-11-21 让人闻风丧胆的 Mysql 锁机制
- 2024-11-21 Java中各种锁的理解
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)