程序猿划水群整理-关于并发锁的机制等

程序猿划水群整理

关于并发锁的机制等

起因是个划水的人装逼瞎问:能不能解释一下乐观锁、悲观锁、偏向锁、轻量级锁、CAS是啥?

乐观锁、悲观锁

我的观点:
在innodb的行表数据锁定的时候好像有涉及到
悲观是 先锁定 禁止操作 ,乐观是 先标记 二次操作判断禁止操作 ?是这样吗

【肯定不是啊! 不过印象中确实是有类似的说法。。。。。】


金小水的说法:
悲观锁是指你拿了这个锁,别人就要阻塞啥事干不了
乐观锁是指你拿了这个锁,别人知道他没锁,可以去干别的事,等你用完锁


这里我觉得跟阻塞没啥子关系 无所谓 ╮(╯_╰)╭ 之后大佬讨论好像是没啥关系

参考些文章看看:

https://blog.csdn.net/u013262534/article/details/81077745
https://blog.csdn.net/qq_32924343/article/details/80451875

在MySQL-InnoDB中确实有悲观与乐观锁的说法:

Shared(乐观锁) and Exclusive Locks(互斥锁):
        InnoDB有两种锁类型,Shared(s) and Exclusive(x) Locks(乐观锁和互斥锁)。
        Shared(s)Locks:允许持有该锁的事务读取数据;
        Exclusive(x) Locks:允许持有锁的事务插入,更新或修改数据;

这里应该也叫共享锁排他锁。【具体可以看MySQL技术内幕-InnoDB存储引擎第六章】

其他的说法:【跟我开始的说法有点像的】

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型[数据库]里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。


关于偏向锁、轻量级锁、CAS

金小水自解释:CAS是一种借助cpu指令保证原子操作的机制

这里我赞同的是:马大佬给的说法:

synchronized在jdk 1.6之前性能很差,因为直接使用操作系统的同步机制,每次都要进行内核态用户态转换比较慢。

1.6的时候引入了偏向锁和轻量级锁偏向锁是优化一个对象锁一直只被一个线程持有的情况,也就是没有多线程的情况,轻量级锁优化的是多线程执行但是没有竞争的情况,比如A持有锁释放锁,然后B持有锁释放锁。

jvm中所有对象都可以作为锁,锁的信息保存在对象头的mark word中,对象的锁状态通过3个bit表示,分别可能是:无锁、偏向锁、轻量级锁、重量级锁。jdk1.6以及之后,默认开启偏向锁,所以mark word默认初始化为匿名偏向状态,也就是状态是偏向锁,但是其mark word中的偏向线程ID为0。

当一个线程进入synchronized代码块,需要持有锁时,发现是匿名偏向状态,会用CAS操作把线程ID从0改成当前线程ID,如果失败,则说明发生竞争,膨胀为轻量级锁。

当这个线程再次持有这把锁时,只要判断是否偏向自己,如果偏向自己就直接成功,性能损耗非常低。**当另外一个线程要获取锁时,偏向锁会膨胀为轻量级锁,**轻量级锁是在线程栈上新建LockRecord,然后把mark word复制到LockRecord中,然后LockRecord的指针指向锁对象,然后把mark word以CAS的方式替换为LockRecord引用。如果CAS失败,则膨胀为重量级锁。释放锁时先释放线程栈中的LockRecord,然后在CAS的方式把mark word替换回去。

总结来说偏向锁是一次CAS,后面简单判断,轻量级锁是申请和释放都CAS,所以性能都是比较好的。

参考文章:https://github.com/farmerjohngit/myblog/issues/14

我先去看看这个文章先。

看了2遍,还是一脸懵的。不是我这个水平的小白看的东的:

感觉上跟马大佬的说法差不多,就是在java中是有多级锁的转换的,并且会根据征用与CAS操作结果进行升级或解锁。

而操作的CAS并不在,这一层进行实现的。

关于CAS的实现:【马大佬】

【马大佬】:
对应的系统调用
本质上都是依赖操作系统的能力
毕竟是直接使用操作系统的多线程机制
一个是jvm机制,一个java类库

锁机制是Java类库的实现,而CAS是JVM机制与操作系统 来实现的。


关于monitor机制

金小水:我记得synchronize是借助monitor机制
.........
马大佬:那是重量级锁才有monitor对象
金小水:synchronize反编译出来的字节码就是带monitor

参考文章:https://www.jianshu.com/p/7f8a873d479c

Java 提供的 monitor 机制,其实是 Object,synchronized 等元素合作形成的,甚至说外部的条件变量也是个组成部分。JVM 底层的 ObjectMonitor 只是用来辅助实现 monitor 机制的一种常用模式,但大多数文章把 ObjectMonitor 直接当成了 monitor 机制。

Java 对 monitor 的支持,是以机制的粒度提供给开发者使用的,也就是说,开发者要结合使用 synchronized 关键字,以及 Object 的 wait / notify 等元素,才能说自己利用 monitor 的机制去解决了一个生产者消费者的问题。

Java 语言中的 java.lang.Object 类,便是满足这个要求的对象,任何一个 Java 对象都可以作为 monitor 机制的 monitor object。

所以。。马大佬的说法还是比较合理的。


关于 阻塞问题

我觉得周小鱼的说法比较对:

周小鱼:
我感觉cas只是快速失败吧?
如果switch不成功,返回不就是false么

cas原子操作,因为不用考虑阻塞或者说锁的问题,才比较快(?,cas本身应该没有阻塞或者等待什么东西的概念,这边concurrenthashmap只有在cas返回true时才会推出,
如果一直cas失败
那这里一样是阻塞的

cas不保证操作成功就好
图:说明并发不阻塞的情况
CAS图解
false的时候外部重试就好
因为本身没用需要lock的东西,很快
估计是因为锁开销远大于 cas重试的次数

这个的说法,在上面的关于锁与CAS的关系的讨论上,就可以看出来的。

你可以用CAS实现阻塞,可以非阻塞 。 【出自马大佬】


以上观点都是大佬的,与本小白杭无关 ╮(╯_╰)╭

小杭整理 2020-03-09


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小_杭

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

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

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

打赏作者

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

抵扣说明:

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

余额充值