锁总结
2020-09-23 11:09:01 0 举报
AI智能生成
为你推荐
查看更多
互斥锁,共享锁,乐观锁,悲观锁特性总结
作者其他创作
大纲/内容
锁总结
互斥锁
互斥锁是一种独占锁,当线程A加锁成功后,此时互斥锁已经被线程A独占,只要线程A没有释放手中的锁,线程B加锁就会失败,于是就会将cpu转给其它的线程,既然已经释放了cpu,那么B加锁的代码就会被阻塞。
互斥锁加锁失败被阻塞现象是系统内核来完成,加锁失败,内核会将线程置为“睡眠”状态,锁释放后,内核会在合适时机唤醒线程,当获取到锁后,就可以成功执行。
互斥锁加锁失败后,会从用户态陷入到内核态,让内核帮忙切换线程,虽然简化了用锁的难度,但是增加了用锁的开销。
两次线程切换上下文开销
线程加锁失败时,内核会将线程从运行切换到睡眠状态,然后将cpu让给其它线程
锁被释放时,之前睡眠的线程切换到就绪状态,内核会在合适的时机,将cpu让给该线程使用
线程的上下文切换是什么?
当两个线程同属于一个进程,因为虚拟内存是共享的,所以在切换时,虚拟内存保持不动,只需要切换线程的私有数据,寄存器等不共享的数据
线程切换耗时大概在几十纳秒到几微秒之间,如果锁住的代码执行时间较短,那可能上下文切换的时间都比锁住的代码的执行时间还要长。
自旋锁
自旋锁加锁失败后,线程会忙等待,直到它拿到锁
自旋锁通过cpu提供的CAS函数(compare and swap), 在用户态完成加锁和解锁操作,不主动产生线程上下文切换, 所以相比互斥锁来说会快一些,开销也小一些。
加锁包含2个步骤:1.查看锁状态,如果锁是空闲的,则执行第二步2.将锁设置为当前线程持有; CAS将这2个步骤合并成一条硬件级指令,形成原子指令,这样保证2个步骤不可分割,要么不执行,要么都执行完。
当使用自旋锁时候,发生多线程竞争情况下, 加锁失败的线程会忙等待,直到它拿到锁,
自旋锁是比较简单的一种锁,开销小,多核系统下一般不会主动产生线程切换,适合异步,协程等在用户态请求的编程方式,但是如果被锁住的代码执行时间较长,自旋锁会长时间占用cpu资源,所以自旋的时间和被锁住的代码执行时间是成正比的。
自旋锁和互斥锁在加锁失败的时候应对策略不一样:当加锁失败时,互斥锁用线程切换的方式来应对,而自旋锁采用忙等待的方式来应对
互斥锁和自旋锁是最基本的处理方式,更高级的锁都会选择其中一个来实现,比如读写锁,既可以选择互斥锁来实现,也可以基于自旋锁来实现
读写锁
读写锁适用于能明确区分读操作和写操作的场景
工作原理:当写锁没有被线程持有时,多个线程能够并发的持有读锁,多个线程同时持有读锁也不回破坏共享资源的数据,一旦写锁被线程持有,读线程的读锁操作会被阻塞,而且其他写线程的获取写锁的操作也会被阻塞。所以写锁是独占锁,因为任意一个时刻只有一个线程持有写锁,类似互斥锁和自旋锁, 而读锁是共享锁,因为读锁可以被多个线程同时持有。
根据实现不同,读写锁可以分为读优先锁和写优先锁
读优先锁:期望的是读锁能被更多的线程持有,以便提高读线程的并发性,工作方式:当读线程A持有了读锁,写线程B在获取写锁的时候,会被阻塞,并且阻塞过程中,后续来的读线程C仍然可以成功获取读锁,直到读线程A和C释放读锁后,写线程B才可以成功获取读锁
写优先锁:优先服务写线程,工作方式是:当读线程A先持有了读锁,写线程B在获取写锁时,会被阻塞,并且在阻塞过程中后续来的读线程C获取读锁会失败,于是线程C被阻塞在获取读锁的阶段,这样只要读线程A释放读锁后,写线程B就可以成功获取到写锁。
读优先锁对于读线程并发性更高,但是也不是没问题,试着想下,如果一直有读线程获取到读锁,那么写线程将永远获取不到写锁,就造成了写线程饥饿,写优先锁可以保证写线程不会饿死,但是如果一直有写线程获取写锁,那么读线程也会被饿死。
公平读写锁
一种简单的实现方式为:用队列把获取锁的线程排队,不管是写线程还是读线程都按照先进先出的原则加锁即可,这样不会出现饥饿现象。
乐观锁
乐观锁做事比较乐观, 它假定冲突概率很低,它的工作方式为:先修改完共享资源, 再验证这段时间内有没有冲突,如果没有其它线程在修改资源,那么操作完成,如果发现有其它线程已经修改资源,就放弃本次操作, 虽然重试成本很高,但是冲突概率足够低的话,还是可以接受。
乐观锁全程没有加锁,也叫无锁编程
乐观锁去除了加锁操作,但是一旦发生冲突,重试成本很高,所以只有在冲突概率很低,且加锁成本很高的场景,才考虑使用乐观锁。
悲观锁
前面的互斥锁,自旋锁,读写锁都是悲观锁,悲观锁做事比较悲观,它认为多线程同时修改共享资源的概率比较高,于是很容易出现冲突,所以访问共享资源前,先上锁,如果多线程同时修改共享资源的概率较低,可以使用乐观锁
多线程访问的时候,避免不了资源竞争而导致数据错乱的问题,通常为了解决这个问题,都会在访问共享资源之前加锁。
0 条评论
回复 删除
下一页