C++-线程中的锁

1. 互斥锁

互斥锁为阻塞锁,用于控制多线程对他们之间共享资源互斥访问的一个信号量。也就是说为了避免多个线程在某一时刻同时操作一个共享资源。

在某一时刻,只有一个线程可以获取互斥锁,在释放互斥锁之前其他线程都不能获取该互斥锁。如果其他线程想要获取这个互斥锁,那么这个线程只能以阻塞方式进行等待

C++11实现互斥锁

1
2
3
4
5
6
mutex m;
void fun()
{
lock_guard<mutex> gl(m);
//do something...
}

2. 条件锁

条件锁就是所谓的条件变量,某一个线程因为某个条件为满足时可以使用条件变量使该程序处于阻塞状态。一旦条件满足以“信号量”的方式唤醒一个因为该条件而被阻塞的线程。最为常见就是在线程池中,起初没有任务时任务队列为空,此时线程池中的线程因为“任务队列为空”这个条件处于阻塞状态。

一旦有任务进来,就会以信号量的方式唤醒一个线程来处理这个任务

3. 自旋锁

自旋锁是非阻塞锁,与互斥锁的相比,在获取锁失败的时候不会使得线程阻塞而是一直自旋尝试获取锁。当线程等待自旋锁的时候,CPU不能做其他事情,而是一直处于轮询忙等的状态。

自旋锁主要适用于被持有时间短,线程不希望在重新调度上花过多时间的情况。

4. 读写锁

读写锁又成为多读单写锁,共享互斥锁。用于解决读写操作并发的问题,多个线程可以并行读取数据,但只能独占的写数据。

优先级策略

  1. read-prefering 读优先:允许最大并发,但如果争用较多时会导致写饥饿;
  2. wirte-prefering 写优先:能有效避免写饥饿,但会相对的带来读饥饿;
  3. unspecified-priority 不确定优先级:不保证优先读与优先写。

5. 递归锁

递归锁为阻塞锁,提供在成功调用 lock 后,需要相应的调用对应次数的 unlock 才能解除其锁定。