乐观锁和悲观锁,可重入锁和不可重入锁(1)


前言

感觉有一段时间没有写博客了呢。还是再接再厉吧,适当程度的总结能让我自己能够更加深入地巩固和理解自己所学习的一切。

还有,我很懒,而且我还是比较喜欢写日记的,所以常常,我就干脆把日记混合到博客里面了。

其实这四个概念真的还挺简单的。一切东西,关键还是在于如何去使用它们,我记得我初中的时候,科学课本上就已经有了黑洞的概念,而且当时老师给我们的感觉就是已经确定黑洞是实际存在的,但是直到2020年,貌似才真正证实了黑洞实际存在。道听途说,和事实可能会有一些差距,但是我实际上想说的,“很多时候,我们知道一件事情,和将其落实到实际上,这两点其实有着很大的差距。”

好了,不说废话了,我尽可能用尽可能短的文字来说清楚这四个概念之间的区别。


自勉

我,可能是你所见过最疯狂的人。


正文

这两个概念其实是描述锁的两个角度。

乐观锁和悲观锁是什么呢?我们其实都知道当给一个线程获取了一个代码块的锁的时候,其他的线程只能等待这个线程释放了锁之后才能拿到锁进入这个代码块执行对应的操作。

但是进程在等待获取到锁的时候其实什么事情都没法做,而且CPU时间片轮询机制下,从一个线程的上下文切换到另外一个线程的上下文的开销其实远远大于执行一条或者几条CPU指令的时间。

所以我们就想出了一种等效的方式来在一些特定的情况下避免synchronized字段的使用。这个方法就是乐观锁,之前使用synchronized字段强行让线程阻塞的方式其实就是与之相对的悲观锁机制。

悲观锁就悲观在其完全不相信多线程同时执行能让数据维持安全性,从而让特定线程在特定代码块只能通过串行的方式来进行,从而保证了数据的“绝对安全性”,虽然我从来不信所谓的“绝对”和所谓的“运气”。当然,因为让并行的程序强行编程串行,这毫无疑问会让效能大打折扣。

但是乐观锁就不一样了,乐观锁给予CPU所直接支持的一个命令,CAS(compare and swap),这个命令说明白点就是,我给出我的一个预期值。这个预期值往往是我之前从内存中读取时的值,如果我发现内存中的数据和我预期的数值相同。那么就乐观地认为在我对于数据的操作的同时,数据本身并没有发生变化,这样以来我就乐观地将自己修改后的数据更新到内存中。如果不同,那么将新的内存值读取到CPU中,重新执行对应的操作,操作完毕后再次更新数据。

但是乐观锁虽然高效,其实存在三个问题:
1. ABA问题:仅仅根据预期值是否变化来判定数据是否被改变,但是万一数据被改变后,又改了回来,我们无从知晓。
2. 多次执行问题:在一些情况下,可能会出现预期值太多次都不能很好地命中的问题,这样一来其实CAS的优势并不存在
3. 操作对象必须为原子数据的问题

那么这三个问题怎么解决呢?其实多次执行的问题,我们目前并没有办法解决,只能按照实际情况如果发现,命中几率实在太低。那么我们也只能退回到悲观锁来达成同步机制。

ABA问题的解决即是对实例添加一个版本戳,也就是对于该实例的每一次修改,都更新这个版本戳,从而能达到能不仅仅从实例数据有没有变化这一个方面来判断实例是否变化。Java中常见的例子是AtomicMarkableReference,AtomicStampedReference。

至于操作对象必须为原子化操作,这个属于待优化内容而并非问题,我们通过equals来判定实例本身是否发生过变化,如果发生变化,则视作为不命中,则重新再执行一次数据操作。这个对于实例比较大的情况下,命中率依然会一直降低。所以虽然乐观锁性能的确比悲观锁要好,但是悲观锁并非毫无用武之地,该需要老将出马还是需要老将出马的,毕竟老将虽然没有小将那样的活力,但是却有着小将所没有的经验!


后记

本来以为能够几句话把四个概念讲清楚的,但是万万没想到竟然光讲前面两个概念就洋洋洒洒写了这么多= =,只能分两个部分来讲了= =,剩下的半篇我明天会补上滴= =

乐观锁和悲观锁,可重入锁和不可重入锁(1)相关推荐

  1. 线程调度、公平锁和非公平锁、乐观锁和悲观锁、锁优化、重入锁

    1. 线程调度 线程调度指的就是给线程分配使用处理器的过程.主要的调度方式有两种:协同式调度和抢占式调度. 1.1 协同式调度 线程完成自己的任务之后主动通知系统切换到另一个线程上. 优点: 实现简单 ...

  2. zbb20180929 thread 自旋锁、阻塞锁、可重入锁、悲观锁、乐观锁、读写锁、对象锁和类锁...

    1.自旋锁 自旋锁可以使线程在没有取得锁的时候,不被挂起,而转去执行一个空循环,(即所谓的自旋,就是自己执行空循环),若在若干个空循环后,线程如果可以获得锁,则继续执行.若线程依然不能获得锁,才会被挂 ...

  3. java dom4j读写锁,java锁的深度化-重入锁,读写锁,乐观锁,悲观锁

    1.重入锁 目的:避免死锁的现象 锁作为并发共享数据,保证一致性的工具,在java平台有多种实现synchronized(重量级)和ReentrantLock(轻量级)等等,这些已经写好提供的锁为我们 ...

  4. Juc07_乐观锁和悲观锁、公平锁和非公平锁、递归锁(可重入锁)、死锁及排查、自旋锁

    文章目录 ①. 乐观锁和悲观锁 ②. 公平锁和非公平锁 ③. 可重入锁(又名递归锁) ④. 死锁及排查 ⑥. 自旋锁 ①. 乐观锁和悲观锁 ①. 悲观锁(synchronized关键字和Lock的实现 ...

  5. java中的锁(悲观锁、乐观锁、可重入锁、不可重入锁、公平锁、非公平锁、自旋锁、阻塞锁...)

    Lock接口 1.简介.地位.作用 ① 锁是一种工具,用于控制对共享资源的访问 ② Lock和synchronized,这两个是最常见的锁,它们都可以达到线程安全的目的,但是在使用和功能上又有较大的不 ...

  6. Java中的锁机制 -- 乐观锁、悲观锁、自旋锁、可重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁、重量级锁、轻量级锁、偏向锁、分段锁、互斥锁、同步锁、死锁、锁粗化、锁消除

    文章目录 1. Java中的锁机制 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 可重入锁(递归锁) 1.5 读写锁 1.6 公平锁 1.7 非公平锁 1.8 共享锁 1.9 独占锁 1.1 ...

  7. 自旋锁、阻塞锁、可重入锁、悲观锁、乐观锁、读写锁、偏向所、轻量级锁、重量级锁、锁膨胀、对象锁和类锁

      1.自旋锁 自旋锁可以使线程在没有取得锁的时候,不被挂起,而转去执行一个空循环,(即所谓的自旋,就是自己执行空循环),若在若干个空循环后,线程如果可以获得锁,则继续执行.若线程依然不能获得锁,才会 ...

  8. 共享锁、排他锁、互斥锁、悲观锁、乐观锁、行锁、表锁、页面锁、不可重复读、丢失修改、读脏数据...

    作者:T-Birds blog.csdn.net/weixin_36634753/article/details/90815755 共享锁(S锁): 又称为读锁,可以查看但无法修改和删除的一种数据锁. ...

  9. 详解各种锁:CAS、共享锁、排它锁、互斥锁、悲观锁、乐观锁、行级锁、表级锁、页级锁、死锁、JAVA对CAS的支持、ABA问题、AQS原理

    共享锁(S锁) 又称为读锁,可以查看但无法修改和删除的一种数据锁.如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排它锁.获准共享锁的事务只能读数据,不能修改数据. 共享锁下其它用 ...

最新文章

  1. java数据结构堆_Java 数据结构-堆实现
  2. InetAddress.getLocalHost()详解及异常处理
  3. mysql 5.6 初始化_MySQL 5.6 关于登陆的初始化设置
  4. 开源免费的.NET图像即时处理的组件ImageProcessor
  5. 深度linux内核升级,深度操作系统 2020.11.11 更新发布:内核升级
  6. GCD学习(五) dispatch_barrier_async
  7. 洛谷 P1164:小A点菜(DP/DFS)
  8. java与javaw运行jar程序
  9. 愚人节里的巧合与必然:BAT等亮出的AI招牌故事
  10. Android APK脱壳--腾讯乐固、360加固一键脱壳
  11. vue-miniQQ——基于Vue2实现的仿手机QQ单页面应用(接入了聊天机器人,能够进行正常对话)...
  12. 能不能算是PLSQL Developer的锅?
  13. WPS怎么在线转换成Word,WPS转换成Word的操作步骤
  14. Unity SKFramework框架(二十四)、Avatar Controller 第三人称控制
  15. Android从零开始搭建MVVM架构(3)——ViewModel
  16. Quartus II 11.0破解要点(与低版本的不同)
  17. Excel数据分析之数组
  18. jarvisoj_level0
  19. com.android.ut是什么文件,妙用UT数据文件夹%AppData%\uTorrent
  20. MFC-局域网聊天工具bug集锦

热门文章

  1. kisboot.sys无法启动系统_Linux系统无法启动的解决方法
  2. jsp里面java和js交互_jsp与js交互实例 | 学步园
  3. Linux查看进程的线程信息
  4. Mysql之alter用法汇总
  5. JsonCpp的简单使用方法
  6. stm32c8t6的can通信实验代码_TCP的连接建立与关闭状态及数据传输通信过程【含有 PHP socket API 测试实验代码】...
  7. oracle正则表达式截断,在oracle中使用正则表达式截取字符串
  8. adding oracle jvm 慢,java – 什么JVM优化导致这些性能结果?
  9. 【以太坊】搭建测试网络之ubuntu系统安装node.js
  10. php的echo 和 return的区别