各种锁
来源:互联网 发布:mac sai 压感 编辑:程序博客网 时间:2024/06/03 01:42
1. 互斥锁
互斥锁,是一种信号量,常用来防止两个进程或线程在同一时刻访问相同的共享资源。可以保证以下三点:
原子性:把一个互斥量锁定为一个原子操作,这意味着操作系统(或pthread函数库)保证了如果一个线程锁定了一个互斥量,没有其他线程在同一时间可以成功锁定这个互斥量。
唯一性:如果一个线程锁定了一个互斥量,在它解除锁定之前,没有其他线程可以锁定这个互斥量。
非繁忙等待:如果一个线程已经锁定了一个互斥量,第二个线程又试图去锁定这个互斥量,则第二个线程将被挂起(不占用任何cpu资源),直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。
从以上三点,我们看出可以用互斥量来保证对变量(关键的代码段)的排他性访问。
2. 自旋锁
POSIX threads(简称Pthreads)是在多核平台上进行并行编程的一套常用的API。线程同步(Thread Synchronization)是并行编程中非常重要的通讯手段,其中最典型的应用就是用Pthreads提供的锁机制(lock)来对多个线程之间共 享的临界区(Critical Section)进行保护(另一种常用的同步机制是barrier)。
Pthreads提供了多种锁机制:
(1) Mutex(互斥量):pthread_mutex_***
(2) Spin lock(自旋锁):pthread_spin_***
(3) Condition Variable(条件变量):pthread_con_***
(4) Read/Write lock(读写锁):pthread_rwlock_***
Pthreads提供的Mutex锁操作相关的API主要有:
pthread_mutex_lock (pthread_mutex_t *mutex);
pthread_mutex_trylock (pthread_mutex_t *mutex);
pthread_mutex_unlock (pthread_mutex_t *mutex);
Pthreads提供的与Spin Lock锁操作相关的API主要有:
pthread_spin_lock (pthread_spinlock_t *lock);
pthread_spin_trylock (pthread_spinlock_t *lock);
pthread_spin_unlock (pthread_spinlock_t *lock);
从 实现原理上来讲,Mutex属于sleep-waiting类型的锁。例如在一个双核的机器上有两个线程(线程A和线程B),它们分别运行在Core0和 Core1上。假设线程A想要通过pthread_mutex_lock操作去得到一个临界区的锁,而此时这个锁正被线程B所持有,那么线程A就会被阻塞 (blocking),Core0会在此时进行上下文切换(Context Switch)将线程A置于等待队列中,此时Core0就可以运行其他的任务(例如另一个线程C)而不必进行忙等待。而Spin lock则不然,它属于busy-waiting类型的锁,如果线程A是使用pthread_spin_lock操作去请求锁,那么线程A就会一直在 Core0上进行忙等待并不停的进行锁请求,直到得到这个锁为止。
所以,自旋锁一般用用多核的服务器。
自旋锁(Spin lock)
自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是 否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。其作用是为了解决某项资源的互斥使用。因为自旋锁不会引起调用者睡眠,所以自旋锁的效率远高于互斥锁。虽然它的效率比互斥锁高,但是它也有些不足之处:
1、自旋锁一直占用CPU,他在未获得锁的情况下,一直运行--自旋,所以占用着CPU,如果不能在很短的时 间内获得锁,这无疑会使CPU效率降低。
2、在用自旋锁时有可能造成死锁,当递归调用时有可能造成死锁,调用有些其他函数也可能造成死锁,如 copy_to_user()、copy_from_user()、kmalloc()等。
因此我们要慎重使用自旋锁,自旋锁只有在内核可抢占式或SMP的情况下才真正需要,在单CPU且不可抢占式的内核下,自旋锁的操作为空操作。自旋锁适用于锁使用者保持锁时间比较短的情况下。
针对数据加锁,而不是代码。中断和锁。。。是tmd的两回事
当一个中断处理程序去试图获取一个已经被获取的自旋锁时,它会自选,但是获取到这个自旋锁的程序无法返回也就无法释放,这样造成了双重请求死锁。但是需要关闭的是当前处理器上的自旋。
3. 读写锁
在编写多线程的时候,有一种情况是十分常见的。那就是,有些公共数据修改的机会比较少。相比较改写,它们读的机会反而高的多。通常而言,在读的过程中,往往伴随着查找的操作,中间耗时很长。给这种代码段加锁,会极大地降低我们程序的效率。读写锁就是为这种情况而生的。
1. 进行读操作时会进行再次加锁和解锁操作,计算开销比较大,因此对锁内计算比较小的操作不适合使用读写锁。
2. 如果读操作比较密集,使得rwLock.m_icount永远不可能为0,因此会使写操作线程饿死。
4. 可重入锁
嵌套锁这个概念,主要是为了根据编程中的一种情形引申出来的。什么情况呢,我们可以具体说明一下。假设你在处理一个公共函数的时候,因为中间涉及公共数据,所以你加了一个锁。但是,有一点比较悲哀。这个公共函数自身也加了一个锁,而且和你加的锁是一样的。所以你的程序一辈子也获取不了这个锁。
5. 临界区
每个进程中访问临界资源的那段代码称为临界区(Critical Section)(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。
6. 原子操作
原子操作可以保证指令以原子方式执行---执行过程不被打断。原子性确保指令执行期间不被打断,要么全部执行完,要么根本不执行。
顺序要求指的是:即使两条或多条指令出现在独立的执行线程中,他们本该的执行顺序依然要保持。
typedefstruct { volatile int counter; } atomic_t;
typedefstruct { volatile long counter; } atomic64_t;
7. 自动锁
利用了自动变量在生命周期结束时调用析构函数的特性。Android中有无数的自动锁。注意,当自动锁是不可重入锁的时候,两次调用同一把锁会死锁
- 各种锁
- Linux中的各种锁
- linux各种锁笔记
- mysql各种锁总结
- IOS 各种锁
- Linux中的各种锁
- iOS 多线程 各种锁
- Linux:各种锁
- Java中的各种锁
- 各种锁整理
- Linux中的各种锁
- iOS 各种 锁
- 认识各种锁
- MySQL中的各种锁
- iOS 中的各种锁
- 各种
- 各种
- 各种~~
- hashmap实现原理浅析
- Java虚拟机结构(二)
- SQL Server再学习(1)——varchar、nvarchar、char的区别
- DatePicker - 日期选择插件
- 关于Android sdkmanager目录结构的总结
- 各种锁
- A glance on VDBI
- 【源代码】java.util.Stack & Queue
- 十三、网络流
- 文章标题
- django 自定义auth的中间件的验证
- 淘宝 项目 管理
- 关于eclipse新建项目问题
- 抽象类、抽象字段、抽象方法