一、线程锁
- 互斥锁
- 自旋锁
- 读写锁
- 条件变量
- 信号量
- 原子锁
什么时候使用互斥锁?什么时候获取自旋锁?
互斥锁:首先它是睡眠锁,会进行线程的切换
自旋锁:循环等待锁 一般用原子锁实现的,会一直占用我们的cpu
lock(mutex);
执行
unlock(mutex);
1、时间上的考虑,时间少就用自旋锁,时间长就用互斥锁
2、设计上,充分利用CPU时候,自旋锁。代表是nginx。(锁的力度要足够小)
互斥锁和自旋锁是可以同时使用的
1、自旋锁+时间2、时间超时后改用互斥锁
二、进程锁
一个机器中的进程间竞争资源的锁。nginx把以下结构放在共享内存中。
nginx进程锁有三种方式的实现:
1、只支持原子锁、自旋锁
2、既支持原子操作有支持信号量,自旋锁+互斥锁
3、文件锁
ngx_shmtx_t放在共享内存中。
三、分布式锁
实现方案:redis、数据库、zookeeper
为什么说分布式锁比较难实现?如何保证分布式锁
1、进程与数据中心的连接是不稳定的
2、进程是不稳定的,进程随时可能崩掉
redis如何实现分布式锁:
- 方案1:
获取锁:set ["lock",1,nx] setnx["lock",1]
释放锁: del["lock"]
问题:a.如果a进程挂了,就会变成死锁 b.谁可以释放锁,需要确定当前谁获取了锁
在分布式系统中如何区分不同的进程?
pid是依次累加的,可能出现重复,可以通过ip:port:pid:startime 四元组唯一标识进程
- 方案2:
获取锁:set("lock",四元组,nx,ex,30)
释放锁:if get("lock")==进程四元组 redis的lua事务 mysql存储过程一样
del("lock")
问题:a.如果a操作临界资源的时间超过30秒,加一个线程:续时间
b、c、d进程怎么去查询锁?第一种 时间轮训 尝试获取锁 第二中: 监听发布机制+key超时机制。