信号量、互斥锁、自旋锁、原子操作

linux内核中有多种内核锁,内核锁的作用是:

多核处理器下,会存在多个进程处于内核态的情况,而在内核态下,进程是可以访问所有内核数据的,因此要对共享数据进行保护,即互斥处理;

Linux内核锁机制有信号量、互斥锁、自旋锁还有原子操作。

一、信号量(struct semaphore):

是用来解决进程/线程之间的同步和互斥问题的一种通信机制,是用来保证两个或多个关键代码不被并发调用。

信号量(Saphore)由一个值和一个指针组成,指针指向等待该信号量的进程。信号量的值表示相应资源的使用情况。信号量S>=0时,S表示可用资源的数量。执行一次P操作意味着请求分配一个资源,因此S的值减1;当S<0时,表示已经没有可用资源,S的绝对值表示当前等待该资源的进程数。请求者必须等待其他进程释放该类资源,才能继续运行。而执行一个V操作意味着释放一个资源,因此S的值加1;若S<0,表示有某些进程正在等待该资源,因此要唤醒一个等待状态的进程,使之运行下去。

信号量是选择睡眠的方式来对共享工作停止访问的。

也就是说信号量通过PV操作同步解决了进程/线程对临界资源利用的冲突问题;

二、互斥锁:(mutex_lock)

互斥锁同样也是对线程间(不能对进程)同步和互斥的一种另一种机制。

互斥锁更多的是强调对共享资源的锁定作用,当一个线程占用了当前共享资源,使用互斥锁将其lock住之后,其他线程就无法访问,必须等到unlock之后,其他线程才能利用共享资源里面的内容;

互斥锁是选择睡眠的方式来对共享工作停止访问的。

也就是说互斥锁通过对共享资源的锁定和互斥解决利用资源冲突问题;

三、自旋锁(spin_lock):

是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。

4.1、Linux原子概念:

所谓原子操作,就是“不可中断的一个或一系列操作”。

原子操作,就是不能被更高等级中断抢夺优先的操作。你既然提这个问题,我就说深一点。由于操作系统大部分时间处于开中断状态,所以,一个程序在执行的时候可能被优先级更高的线程中断。而有些操作是不能被中断的,不然会出现无法还原的后果,这时候,这些操作就需要原子操作。就是不能被中断的操作。

硬件级的原子操作:在单处理器系统(UniProcessor)中,能够在单条指令中完成的操作都可以认为是“原子操作”,因为中断只发生在指令边缘。在多处理器结构中(Symmetric Multi-Processor)就不同了,由于系统中有多个处理器独立运行,即使能在单条指令中完成的操作也有可能受到干扰。在X86平台生,CPU提供了在指令执行期间对总线加锁的手段。CPU上有一根引线#HLOCK pin连到北桥,如果汇编语言的程序中在一条指令前面加上前缀"LOCK",经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低,持续到这条指令结束时放开,从而把总线锁住,这样同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中的原子性。对于其他平台的CPU,实现各不相同,有的是通过关中断来实现原子操作(sparc),有的通过CMPXCHG系列的指令来实现原子操作(IA64)。本文主要探讨X86平台下原子操作的实现。

以上总结几点:

互斥锁与信号量的区别:

1、信号量一般以同步的方式对共享资源进行控制,而互斥锁通过互斥的方式对共享资源对其进行控制;

2、信号量可以对进程的共享资源进行控制,而互斥锁不行;

3、信号量的值为非负整数,而互斥锁的值只能为0或1;

4、互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到;mutex和二值信号量的区别在于mutex必须是同一个进程来释放

自旋锁与互斥锁的区别:

1、因为自旋锁不会引起调用者睡眠,所以效率比较高

2、自旋锁比较适用于锁使用者保持锁时间比较短的情况。

3、自旋锁容易造成死锁,所以需要安全使用它;

参考

https://www.cnblogs.com/linhaostudy/p/6670693.html

发布了137 篇原创文章 · 获赞 44 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_38769551/article/details/105151826