Note: TWLKH: 浅谈Semaphore与mutex
各种IPC的方式
像其他的方式都有System V和POSIX两种,而Mutex,是不是暗示着什么呢?可以看一下Mutex何时产生的
UNIX的两大主要分支AT&T的System three & V 和 BSD发行版,POSIX IPC是更后面的,Mutex是在POSIX中才定义的。
更详细的
1962年Dijkstra是首先提出共享资源会存在问题的,Busy waiting-> Binay Semaphore -> Counting Semaphore -> MUTEX
从这个时间线还可以看出,MUTEX是在Binary Semaphore之后很久才有的,也说明他们不完全是一回事,后面会详细说
Semaphore - 1
x=x+1实际上会涉及几步,如果两个thread同时Load x,x可能加1,出现问题
Semaphore - 2
所以,需要加锁保护 Critical Section. 在这个例子中Semephore 相当于房间的钥匙
Semaphore - 3
Semaphore - 4
意外的释放,释放多次
Semaphore - 5
Recursive Deadlock: 临界区中是递归调用
Task-Death Deadlock: 一个任务Death,另外任务都要wait
Semaphore - 6
由于cs(Critical Section)的存在,可能导致Low Priority Task 比High Priority Task先执行完,导致优先级倒置
Semaphore - 7
将Semaphore当做Signal用
好处:不必成对,一对多,实现Broadcast
坏处:Accidental Release,意外的V操作
MUTEX - 1
MUTEX就等同于Binary Semaphore吗?
与Semaphore最大区别,Mutex有ownership原则
Accidental Release: 解决,因为是成对的,不会被第二者意外释放
Recursive Deadlock: 解决,允许re-lock且成对释放,因此不会造成问题
Task-Death Deadlock: 解决,已获得锁的Taks A发现death时,可以将ownership转移出去(给其他在等待这个锁的),或者通知所有等待这个锁Error
MUTEX-2
Priority Inversion: 解决,且有两种解法
注:Priority Sealing、Highest Locker和 Priority Ceilling Protocol 意思相同吗?应该吧。Priority Ceilling Protocol在pthraed mutex源代码中有,故使用这个
MUTEX-3
就很像Rust中的ownership转移,
Task Low可以将the ownership of Mutex转移给Task high,所以Task high能够在low之前完成,从而解决了priority inversion问题
MUTEX-4
将cs视为最高优先级,新任务不会抢占前一个任务的cs,例如Task Mid会等前面3个cs执行完再执行
这样,不看cs的话是实时抢占;看cs的话,就不算实时抢占了
MUTEX-5
这种死锁,没法解决,只能程序员写代码是自己注意,破坏死锁四个条件中的至少一个
接下来讨论一下什么场合应该使用Semaphore,什么场合使用Mutex
使用时机- 1
多资源就适合Semaphore吗?不是的
如果不区分具体资源属于谁,比如停车场,就适合Semaphore;如果需要区分,比如两个房间不应该用同一个钥匙,所以应该是两个Mutex来实现,而不是Semaphore
使用时机-2
将Semaphore当做Signal使用:ISR(中断服务程序),接受到中断信号跳转到服务程序,比较适合
使用时机-3
Mutex:用于互斥资源,比如系统设备Device;尽可能使用在底层(leaf node)
使用时机-4
总结:Mutex与Semaphore最大的差异,Mutex用在哪,Semaphore用在哪,mutex在glibc中
mutex是在glibc中实现的,在pthread.h中可以看到
例如mutex的种类:
例如,还有前面讲到的priority ceiling 和 priority protocol
mutex对应的属性设置在mutexattr中,可以看到pthread_mutexattr_setprioceiling.c 和 pthread_mutexattr_setprotocol.c 的定义
使用时机 - 5
semaphore基于spinlock, mutex基于semaphore
semaphoe和mutex等都是blocking的
lock-free有RMW和CAS两种,no-lock可以用circular buffer来实现
.....等等
Quiz
1. 实现Thread Barrier
其实pthread中实现了一个pthread_barrier,模仿一个
2. 实现Shared Queue
就是生产者-消费者模型,一个测试提示,使用-fsanitize=thread
Ref: https://www.youtube.com/watch?v=JEXwO_EoyZo&ab_channel=TaiwanLinuxKernelHackers