各种锁:自旋锁/互斥锁/读写锁/分布式锁

锁在计算机的世界里随处可见,当大家都想操作一个资源的时候,如果一窝蜂涌进来,就会出事的。
举个例子,加入说有2个线程都在操作一个共享资源(一个int),给他+1。我们知道+1不是原子操作,所谓原子操作,就是如果这个操作开始执行了,那么就不会被打断。看过汇编的同学都知道,+1需要先mov然后在add,如线程1mov了,然后执行线程2的mov,就会出问题。轻则数据错误,重则程序崩溃。感觉这个例子不太恰当,还是领会精神吧。为了保护我们的操作,那么就需要使得这个共享资源的操作变成原子的,这就需要锁了。
在并发编程中,尽量少用锁,能不用就不用,因为锁的开销很大很大。首先在业务层面进行分隔,尽量让不同的执行单元操作各自独立的数据,如果不可避免要用到锁,那么锁的范围要尽量小。

自旋锁vs互斥锁

举个例子

  • 互斥锁:假如说你想进入一个房间,但是这个房间里已经有人了。那么就进不去,这个时候你就先睡一觉,等里边的人出来把你叫醒,然后你再进去。
  • 自旋锁:还是这个房间,房间里有人,你不会睡着,只会每过一分钟就看房间里的人出来了么,如果没出来,那么就继续不停查看。如果出来了,你就进去。

对应到系统,就是你这个线程想获取这个锁,但是这个锁被别的线程持有了,那么你这个线程就得休眠,等待锁释放后再被唤醒。要知道,休眠再唤醒的开销很大,所以就出了自旋锁。自旋锁不会休眠,会不停的尝试。

特征 使用场景
自旋 不会休眠,不停重试,直到获得锁 多核,如果单核的话,就一直自旋,执行线程反而得不到时间片。锁住的代码执行时间很短。因为休眠再唤醒的开销很大。如果时间短,那么自旋的开销就很小。要多核
互斥 休眠,等锁被释放才会被唤醒 锁住的代码要执行很久,如果是自旋锁,就会不停尝试,被锁住的代码分不到足够的时间片,但是性能下降

读写锁

场景:读多写少
条件:

  • 只要没有写锁,就能获取到读锁
  • 只有没有任锁,才能获取到写锁

本博客欢迎转发,但请保留原作者信息
github:codejuan
博客地址:http://blog.decbug.com/