文章目录

  • 问题来源
  • 什么叫锁
  • 为什么会有锁
    • 私有制和公有制
    • 资源的稀缺和充足
    • 保证隐私
    • 僧多肉少
    • 为什么会有锁
  • 都有什么样的锁
    • 讲不讲素质要不要排队—公平锁和非公平锁
    • 虽然很多人排队,但里边未必没有坑位—乐观锁和悲观锁
    • 进了大门,能不能直接进入具体坑位—可重入锁和不可重入锁
    • 一个坑位只能蹲一个人,那坑位外边的洗手区呢—共享锁和排他锁
    • 要不要一直排队等,还是先去旁边抽根烟—自旋锁和适应性自旋锁
  • 有没有开不了的锁
  • 那些被忽略的锁
    • final关键字
    • volatile关键字
    • public、private、protected
  • 神图:公厕示意图
问题来源
  • 还是有一次面试呀,人家就问我:说说锁的实现原理吧。 我当时的反应就是:小朋友,你是不是有很多的问号?第一反应,可以用某某某的一首某某歌的词来形容:最想说的话,我该从何说起,你是不是也像我一样在想呢?
  • 说说为什么我会有点懵逼的感觉吧。第一:在我理解,什么叫原理,就是原始的理论或者最初的道理。一个原理可以约等于一种理念,是不管谁拿着这个原理,都可以撸出一种实现的。道理只有一个,但实现方式千千万万。第二:虽说面试的时候,前提讨论背景是Java语言环境,但即使是Java里边的锁,也分很多的吧。常见通俗的,就说Synchronized关键字实现的是不是一种锁?ReentrantLock实现的是不是一种锁?ReadWriteLock实现的又是不是一种锁?第三:就上边说的这三种,在我看来也是不同类型范围的锁的不同实现方式,万万达不到原理层面。 PS:我后来知道了,他是想让我说Synchronized是怎么实现的。
  • 昨天还跟一个朋友说起这个事儿,他是觉得我有点较真了,面试的时候,就是要说出对方想听的,然后大家都认可的答案。说来也奇怪,我问他:来来来,我们说说Java里边锁的实现原理吧?哇塞,他就立马开始说Synchronized的什么monitorenter和monitorexit指令,什么flag的ACC_SYNCHRONIZED标志了。我也很懵了,或许是我真的太固执吧。只是内心深处,私以为:概念、原理性的东西,一定要是清晰明确的,不能混为一谈。后来说着说着我也不想多说,就再问了朋友一个问题:好,你说了那么多非常的好,再问你一个问题:为什么会有锁? 至此,我把天聊死了。 其实,我还有好多问题呢:有无所谓的万能锁?锁的作用是啥?怎么实现自己的锁?在A场景到底需不需要锁,为什么需要锁,需要什么样的锁? 多说无益,我终究是又把天聊死了。
什么叫锁
  • 《辞源》曰:“锁,古谓之键,今谓之锁。”《辞海》解释为:“必须用钥匙方能开脱的封缄器”。 再纵观历史,锁的产生,伴随着私有制的产生。不知道有么有童鞋记得中学的一篇文章《礼记-大同》中的“故外户而不闭“,不闭,咱们可以理解为不加锁的意思。
  • 想一下,为什么家里的们要上锁?或者说是自己的笔记本要加开机密码—我认为设置密码,本质上就是加锁? 什么情况没有锁,换种说法是:什么情况不必有锁?
为什么会有锁
私有制和公有制
  • 回到《大同》篇,人们之所以不必户,因为是大同社会呀。什么是大同社会,天下为公,就是资源是大家的,没有人有权利或者有必要把某个东西加锁。PS:额,有点类似共产主义哈。但如果用个Java关键词来说的话,大同就是public。
资源的稀缺和充足
  • 想象一下我们的家为什么会有锁?怕贼偷啊,他把东西偷了,我就没有了,他富我穷。那人为什么要偷东西呢?因为他没有自己的资源。或者说资源只有一份,你现在搁家里锁起来,就意味着我没办法拥有,好东西谁都想要。但如果,资源很充足呢?就跟咱们常说的,现在有些人在路上看见一块钱,都不带弯腰去捡的,这时候敞开了送都不要,还搞个锁干啥使呢?
保证隐私
  • 其实生活中还有一种情况,比如说:小姑娘在家换衣服,明明大门是锁了的,为什么还要把自己房间的们也锁上?所以有时候加锁,也因为需要很强的隐私性,我在一个空间里干了什么我不希望别人知道。
僧多肉少
  • 这一点和第二点有些许不同。就是说,尽管资源很稀缺,现在手里就只有1两二师兄的肉肉,但你确定全世界就只有你一个人而已,这时候需要锁吗?就跟班里只有一个学生一样,你永远都是第一。
为什么会有锁
  • 因为有些人惦记我的美貌,并想据为己有。 要么加锁藏起来保证我独自私有,要么干掉”有些人“。当我不能手染血腥”杀进程、杀线程“的时候,我只能把我自己lock起来了。PS:真要说起来,加锁是一种牺牲自己,保护别人的手段。
都有什么样的锁
  • 事已至此,我要祭出大招了。请看文章结尾的图,公厕示意图。PS:历史中的博客有说过为啥我一贴图就是祭出大招。
讲不讲素质要不要排队—公平锁和非公平锁
  • 大家都排着队上厕所,你说你实在很急,得了,有人能憋有人憋不得。或者有个孕妇炎炎烈日站着排队,你说这时候让不让这些很急或者很需要被照顾的人排到第一个去呢? 不让就是公平锁,管你什么呢,大家统一排队,先到先蹲坑。让了就是非公平锁,各凭本事,有些人可能来了2小时都没个坑位,有些人刚来就有坑位了。比如:ReetrantLock通过构造函数指定其的公平性,如果是公平的,那么所有的线程都加入队列中等待,先进先出。Synchronized是非公平的,没有那么个队列呀,大家来了就到门口抢呗,谁狠谁蹲坑。
虽然很多人排队,但里边未必没有坑位—乐观锁和悲观锁
  • 就跟上厕所一样的,有时候根本就是下意识的看着很多人排着队,然后就以为是里边没有坑位了,然后自己还默默的加入到队伍后边,排呀排呀。突然有一个人没排队进去了,然后又XXX了一会子开门出来了。哈哈哈,其实很可能通用坑位没人用啊。或者大家都排着队想去洗洗小手,或者排队的都是女同胞,其实作为男同胞的你是有专属坑位的。Synchronized是悲观的,只要有人从大门进去了,里边就一定没有坑位了。CAS认为是乐观的,先去看看再说,有人就老实排着,没人就蹲坑。在Java里边的话,用各种锁,不仅限于Synchronized,都是一种悲观的态度,总有刁民想害朕,朕先搞把锁把自己保护起来。而无锁编程则是乐观的,虽说总有刁民想害朕,但等他来害我的时候,我再把他打死,平常我就专心练我的绝世神功。
进了大门,能不能直接进入具体坑位—可重入锁和不可重入锁
  • ReetrantLock和Synchronized都是可重入锁。如图所示,一共3个坑位,钥匙有3把,只要你拿到大门的钥匙,就可以进去蹲坑。可重入锁很有好处的耶,试想一下,当你兴高采烈拿到大门钥匙的时候,总觉得下一秒就可以冲进去蹲坑,谁知道,里边的坑位还有锁,并且里边还排着一堆人,这时候,只能说你完了,完了,尿裤子了,等”si“吧,女票在外边等那么久都等不着你,等待超时,女票远走。哦豁,都完了。
一个坑位只能蹲一个人,那坑位外边的洗手区呢—共享锁和排他锁
  • 一个坑位只能蹲一个人,你蹲了,我就不能蹲。但洗手区,你可以洗,我可以洗,他可以洗,咱们可以一起洗。ReentrantLock和Synchronized是排他的,我占了这个坑位,你就只能等着。但ReadWriteLock不同。虽然我拿了大门钥匙,但我只独占坑位,其他人想蹲坑需要等待,但只想洗洗小手的话,则大胆的往前走就阔以了。所以也会经常发些,公厕常理来说是不关大门甚至没有大门锁的,只是每个坑位才有关门和开门的概念。
要不要一直排队等,还是先去旁边抽根烟—自旋锁和适应性自旋锁
  • 自旋锁,就是你看着有人排队,然后你一直在队伍里边排着,直到你等到了一个坑位,然后离开。炎炎烈日或者凛冽寒风,可怜的你就站在队伍里排着,很消耗生命体能的。在程序里应该是耗费CPU吧,但也有好处,就是你可以第一时间拿到坑位。适应性自旋锁,举个栗子吧:你现在看见有3个人进入大门进了小坑位了,这时候,突然有一个人出来洗小手手,但是突然她又进去蹲坑了—传说中的偏向锁。这个时候是个人都会在这等的吧,希望就在不远的前方了。—据说是轻量级的锁。但是,万万没想到啊,这人也是蹲坑界的王者,你都等30分钟了,还没有出来。等个鬼,咱不等了。然后大喊一声:里边的勇士,假如出坑了,请大喊一声有坑位了,小的立马就来。——好像是重量级的锁。这时候,有好处也有坏处。好处就是不用一直站着等啊,坏处就是得来回跑,其实哪个耗费体能多,还真说不准,看等待的时间长短吧。
有没有开不了的锁
  • 不知道有缘路过的众位勇士有木有经历过这么一个名场面。厕所里边的人出不来,厕所外边的人进不去,大家一直在吵吵,有些本来想蹲坑后来又不想的人被困在里边,有些本来只是进去洗个小手手的人,也被困在里边。我是在春运的时候,在火车站经历了N次这样的名场面。这其实,就是一把开不了的锁。而且除了有坑位的门这种有形的锁,还有想挤出来的人,和想挤进去的人之间形成的无形的锁。也再次说明,锁是一个抽象概念,不是一个具体的实物。在Java编码中也是一样的,并不一定是咱们声明了一把锁,比如用个Synchronized或者别的啥啥啥,才会有锁的出现。比如说你明明就没有声明锁呀,结果整个进程都形成死锁了。所以,但凡有资源竞争的地方,都不是挂了一把锁,才有锁的,锁是个保护机制。
  • 从原则上说,没有开不了的锁,也没有一定要开的锁。根据加锁的不同目的,和获取锁的不同目的,可以有分别不同的行为。问题是:是否愿意放弃被锁住的东西?是否愿意去保护被锁住的东西?被锁住的东西是否能有个完美的替换品?但一个线程一定要完整获取被锁住的那个东西时,而锁住东西的那个线程不愿意放手时,这就是一把开不了的锁—死锁。形成死锁的四个条件:互斥条件、请求与保持条件、 不剥夺条件、循环等待条件。对于编程而言是锁,是死锁。对于人而言,就是结,死结。只要愿意有任意一方任意一个环节作出让步,都不会有开不了的锁。
那些被忽略的锁
  • 难道只有Synchronized、ReentrantLock这呀那的才算是锁吗?那CAS也没个锁的意思,可也还是锁呀。所以锁终归只是一种抽象的东西,只是一种约定:我上了锁,大家都不许破坏争抢。有将约定实体化的,也有放得开看得透不搞锁的。
final关键字
  • final关键字修饰的类、方法、变量,不允许被修改。什么不能被继承啊,什么不能被重写可以重载呀,咱们都先不说。这个关键字,真是太大气也太慈悲了,为什么这么说呢,这资源是我的呀,我插上旗帜落下我自己的记号已经成为我独有的了。我本可以通过围栅栏,加锁的方式让其他人都得不到。但是,我把资源加上保护罩,公开陈列展出,允许你看,允许你用,甚至允许你山寨,只要你不破坏我原来的样子就可以了。像String,Integer、Array、Math等,我所有的好东西,大家谁都可以看看,拿着用。有时候,我们为什么要加锁,不过就是因为我不希望属于我的东西,被别人改动破坏。所以,保证私有,有时候的本质目的其实是保证不可变就阔以了。
volatile关键字
  • 如果说final关键字大气又慈悲,volatile关键字就跟个慈善家似的。别人家的公厕只能在外边排队等,但volatile家的允许你进去洗手区域等。一旦有人出坑,你立马就可以进去。而不是像排队在外边的人一样,就算有人出了坑位在洗手,他也依然在等待,甚至是以为里边没有可用坑位而原地爆炸。volatile是个善良的人,但善良的人也会有底线,底线就是:当一个人想进,一个人想出的时候,必须先出才能进,传说中的指令重排。要说这个关键字没有锁么?不见得。如果没有锁,为什么必须先出才能再进呢?只是锁的不那么明显。
public、private、protected
  • 这些访问控制关键字,从对自己所持资源的开放程度来说,也能是不同程度的锁。不想说了,突然很困,睡觉来着的。
神图:公厕示意图

锁的实现原理—1,为什么会有锁?相关推荐

  1. python乐观锁代码实现_Elasticsearch系列—并发控制及乐观锁实现原理

    概要 本篇主要介绍一下Elasticsearch的并发控制和乐观锁的实现原理,列举常见的电商场景,关系型数据库的并发控制.ES的并发控制实践. 并发场景 不论是关系型数据库的应用,还是使用Elasti ...

  2. 快来学习Redis 分布式锁的背后原理

    以前在学校做小项目的时候,用到Redis,基本也只是用来当作缓存.可阿粉在工作中发现,Redis在生产中并不只是当作缓存这么简单.在阿粉接触到的项目中,Redis起到了一个分布式锁的作用,具体情况是这 ...

  3. 还不知道 Redis 分布式锁的背后原理?还不赶快学习一下

    前言 以前在学校做小项目的时候,用到Redis,基本也只是用来当作缓存.可阿粉在工作中发现,Redis在生产中并不只是当作缓存这么简单.在阿粉接触到的项目中,Redis起到了一个分布式锁的作用,具体情 ...

  4. mysql锁机制为何设计如此复杂_再谈mysql锁机制及原理—锁的诠释

    加锁是实现数据库并发控制的一个非常重要的技术.当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁.加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更 ...

  5. 动态加载laydate 失效_Java对象的内存布局+反射的原理+动态代理+ 并发和锁+文末彩蛋...

    # 一行代码是怎么运行的 首先,java代码会被编译成字节码,字节码就是java虚拟机定义的一种编码格式,需要java虚拟机才能够解析,java虚拟机需要将字节码转换成机器码才能在cpu上执行. 我们 ...

  6. Redis分布式锁的实现原理

    目前基于Redis实现的分布式锁常用的框架是Redisson,它的使用比较简单,在项目中引入Redisson的依赖,然后基于Redis实现分布式锁的加锁与释放锁. Redis分布式锁的底层原理 ​ R ...

  7. 深入分析AbstractQueuedSynchronizer独占锁的实现原理:ReentranLock

    一.ReentranLock 相信我们都使用过ReentranLock,ReentranLock是Concurrent包下一个用于实现并发的工具类(ReentrantReadWriteLock.Sem ...

  8. 多线程—AQS独占锁与共享锁原理

    java.util.concurrent.locks包下,包含了多种锁,ReentrantLock独占锁.ReentrantReadWriteLock读写锁等,还有java.util.concurre ...

  9. java中的账户冻结原理_java可重入锁(ReentrantLock)的实现原理

    前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...

  10. Redis分布式锁的实现原理看这篇就够了~

    2019独角兽企业重金招聘Python工程师标准>>> 一.写在前面 现在面试,一般都会聊聊分布式系统这块的东西.通常面试官都会从服务框架(Spring Cloud.Dubbo)聊起 ...

最新文章

  1. 我自己可以挖矿了!使用Ethereum C++客户端Aleth建一个私有网络,并使用Remix部署一个智能合约
  2. Java之进程与线程练习
  3. LiveVideoStack线上交流分享 (十五) —— 熟悉技术的边界,实现1+1+13
  4. baseresponse响应类_Java response响应体和文件下载实现原理
  5. 题解【luogu2045 方格取数游戏加强版】
  6. TypeError: 'RGB' has type str, but expected one of: bytes(法1)
  7. 【机器学习系列】隐马尔科夫模型第三讲:EM算法求解HMM参数
  8. textContent与innerText
  9. 佳能ir2002g无法扫描到计算机,佳能ir2002g扫描驱动
  10. 南大软院21天学霸养成计划—第6天
  11. 小程序携带参数跳转的方式wx.navigateTo的URL和通过data-传递
  12. Oracle EBS Workflow简介和客制之后的感想
  13. c语言 r语言 java,R语言rJava包安装载入及JAVA环境配置
  14. 在MacOS上构建以太坊开发环境
  15. 【毕业设计】深度学习动物识别系统 - python 卷积神经网络 机器视觉
  16. 宠物店会员管理系统| 宠物店小程序
  17. php中划线,html中下划线、删除线、上划线的样式与用法实例
  18. 晦涩难懂的c语言语句,【c/c 学习心得】晦涩难懂的const关键词,const v.s. 指标值...
  19. c语言(http://c.biancheng.net/view/1714.html)
  20. 服务器怎么跑python_如何在服务器上跑python程序

热门文章

  1. 批量OCR识别图片中的文字
  2. 小米qq音乐|小米音乐qq版
  3. Cannot run program “D:\jdk8\bin\java.exe“ (in directory “C:\Users\Administrator\AppData\Local\JetBra
  4. 报表工具选型对比系列 - 多源关联性能
  5. Word写论文及PPT画论文图的经验总结
  6. office新建word excel ppt时,图标显示异常的问题
  7. 最新最全论文合集——基于机器学习/深度学习的睡眠信号分类
  8. 在html中做框架的页面,网页中的框架(详解)
  9. Navicat数据传输
  10. 互联网日报 | 5月26日 星期三 | 华为鸿蒙操作系统6月2日发布;特斯拉已在中国建立数据中心;百度发起“高考+”计划...