常见的锁策略
前言
在多线程编程中,锁的策略是极其重要的一个概念。因为锁往往是和线程安全相挂钩的,所以在这里了解锁的策略是非常有必要的。
?一.乐观锁和悲观锁
简单介绍下概念:
1.乐观锁
乐观锁就是假设数据一般情况下不会发生冲突,所以在数据真正更新的时候,才会对数据是否真正产生并发冲突进行检测,如果发生冲突了,则返回用户错误信息,让用户决定如何去做。
举个例子:加入现在有一个同学想要找老师问问题
该同学认为 "老师是比较闲的, 我来问问题, 老师大概率是有空解答的". 因此同学直接就来找老师.(没加锁, 直接访问资源) 如果老师确实比较闲, 那么直接问题就解决了. 如果老师这会确实很忙(也就是检测到了冲突), 那么同学 B也不会打扰老师, 就下次再来(虽然没加锁, 但是能识别出数据访问冲突).? ?这个是乐观锁.
2.悲观锁
悲观锁总是假设最坏的情况,所以在每次上锁的时候都认为别人会修改,所以每次去拿数据的时候都会上锁。
举例:还是有个同学想要问问题
该同学认为,老师一定是在忙着的。不管是在上课还是在写教案,该同学都是认为该老师是一直处于忙着的状态。所以该同学就会跟老师给约定个时间来问问题(就相当于加锁操作),在得到肯定回复之后,才会真正的去问问题。如果得到了否定的回答,那就再等一段时间,下次再和老师确定时间。
二.读写锁
- 两个线程都只是读一个数据, 此时并没有线程安全问题. 直接并发的读取即可.
- 两个线程都要写一个数据, 有线程安全问题.
- 一个线程读另外一个线程写, 也有线程安全问题.
读写锁特别适合于 "频繁读, 不频繁写" 的场景中. (这样的场景其实也是非常广泛存在的).也就是读的多,写的少。
三.自旋锁
一般来说,线程在竞争锁的时候失败后,需要放弃CPU,等待之后的调度(这个过程可能有很长),但是其实大部分情况下,虽然当前线程强锁失败了,但是过不了多久,这个CPU就空闲了。此时就没必要放弃CPU,也就是可以一直来竞争锁。这中锁的竞争策略就是自旋锁。
举个例子,假如你在追你的女神,此时你的女神已经和别人在一起了。但是他们俩有可能很快就会分手了,此时你就没必要放弃去追女神(CPU),你每天和她发信息,不断重复尝试,假如她分手了,此时你就能立刻得到。 大概就是这个意思。
🎈挂起锁和自旋锁
四.公平锁和非公平锁、
假设现在有三个线程A B C,A此时先尝试获取到锁成功,然后B尝试获取到锁失败,阻塞等待。此时C也尝试获取到锁失败,阻塞等待。那么此时如果A释放了锁,那么会发生什么?
1.公平锁
遵循先来后到的原则:B比C先来的,当A释放锁之后,B会获取到锁。
2.非公平锁
B和C谁先获取到锁不一定。B 和 C都有先于对方一步可能获取到锁。
注意:synchronized 是非公平锁
五.可重入锁和不可重入锁
1.可重入锁
2.不可重入锁
假如还是刚才的递归例子,如果锁时不可重入的。那么在同一个线程中,在函数递归的过程中,执行到第二次的时候需要加锁,但是这个锁是当前线程在使用并且来进行递归了。那么就会一直等待自己的线程释放自己的锁。那么就很扯淡,自己不想释放锁,自己还得等待自己释放。这种情况就是不可重入锁。
总结:锁策略是需要重点学习和理解的,它适用于任意的多线程编程语言。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!