基本锁介绍

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。基本锁介绍,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1、分类

乐观锁:
	在select的时候不会加锁,是基于程序实现的,所以不会存在死锁的情况。
	适用于读多写少的场景(写的并发量相对不高),可以提高系统的吞吐量。
	因为如果写多的话,乐观锁会有很大机率更新失败,需要不断的自旋执行查找和更新操作。
	自旋的时候会一直占用CPU,会耗费大量的CPU资源。


悲观锁:
	在select的时候就会加锁,采用先加锁后处理的模式,虽然保证了数据处理的安全性,但也会阻塞其他线程的写操作。
	悲观锁适用于写多读少的场景,因为拿不到锁的线程,会将线程挂起,交出CPU资源,可以把CPU给其他线程使用,提高了CPU的利用率。


锁分类:
	悲观锁:具有强烈的独占和排他特性,在整个数据处理过程中,将数据处于锁定状态。适合于写比较多,会阻塞读操作。
	乐观锁:采取了更加宽松的加锁机制,大多是基于数据版本( Version )及时间戳来实现。。适合于读比较多,不会阻塞读

独占锁:互斥锁、排他锁:保证在任一时刻,只能被一个线程独占排他持有。synchronized、ReentrantLock
共享锁:可同时被多个线程共享持有。CountDownLatch到计数器、Semaphore信号量 

可重入锁:又名递归锁。同一个线程在外层方法获取锁的时候,在进入内层方法时会自动获取锁。
不可重入锁:

公平锁: 有优先级的锁,先来先得,谁先申请锁就先获取到锁
非公平锁: 无优先级的锁,后来者也有机会先获取到锁

自旋锁: 当线程尝试获取锁失败时(锁已经被其它线程占用了),无限循环重试尝试获取锁
阻塞锁: 当线程尝试获取锁失败时,线程进入阻塞状态,直到接收信号后被唤醒。在竞争激烈情况下,性能较高

读锁: 共享锁
写锁: 独占排他锁

偏向锁:一直被一个线程所访问,那么该线程会自动获取锁
轻量级锁:CAS):当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,
	其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
重量级锁:当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候(10次),
	还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让他申请的线程进入阻塞,性能降低。
以上其实是synchronized的锁升级过程

表级锁: 对整张表加锁,加锁快开销小,不会出现死锁,但并发度低,会增加锁冲突的概率
行级锁: 是mysql粒度最小的锁,只针对操作行,可大大减少锁冲突概率,并发度高,但加锁慢,开销大,会出现死锁

2、具体锁实现:

1、jvm:

ReentrantLock悲观的独占的可重入的可公平可不公平锁
		synchronized悲观的独占的可重入的非公平锁
			无锁 --> 偏向锁(同一个线程再次获取锁) --> 轻量级锁(自旋) --> 重量级锁

2、mysql:

select ... for update:悲观的独占的
select ... lock in share mode

3、jvm:ReentrantLock + synchronized

	1.单个jvm实例 单机
	2.必须单例
	3.与事务并存问题
	总之,不适合于保证数据库数据可靠性

4、mysql:

	1.直接更新时判断。在更新中判断库存是否大于0 
	update table set surplus = (surplus - buyQuantity) where id = 1 and (surplus - buyQuantity) > 0 ;
		解决jvm锁多例模式锁失效问题 及 事务共存问题
		锁范围控制:条件字段必须创建索引;查询条件必须具体的值
		同一个商品有多个库存时,无法解决。
		无法记录库存变化前后的状态
	2.悲观锁:select ... for update
		库存操作要统一:不能有的操作是select ... for update 而有的操作是普通的select
		死锁风险:多条记录时,加锁顺序要一致
		阻塞及性能问题
	3.乐观锁:version 或者 时间戳(CAS思想)
		ABA问题
		失败需要重试,高并发情况下性能不高
		读写分离情况下导致乐观锁不可靠

5、zookeeper

客户端:ZooKeeper原生客户端、ZkClient、Curator
	前两个客户端参照:https://blog.csdn.net/qq_42349306/article/details/118209298
读操作和设置监听事件之间是有原子性的

阻塞公平锁:
	1.接收到请求时,在/locks节点下创建一个临时序列化节点
	2.判断自己是不是/locks节点下最下的节点:是则获取到锁,不是则监听前一个节点
	3.获取到锁,处理完业务逻辑后,通过delete删除当前节点释放锁。监听当前节点的下一个节点收到通知,重复第二步。

Curator分布式锁源码解读:https://blog.csdn.net/qq_41432730/article/details/123389670

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/188464.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!