线程同步与锁 二元信号量 binary semaphore 信号量 semaphore 互斥量 mutex 临界区 critical section 读写锁  read-write lock 条件变量 condition variable

为了避免多个线程对同一个数据进行读写,我们要将各个线程进行同步。所谓同步,就是指在一个线程访问数据未结束的时候,其他线程不得对同一数据进行访问。

同步最常用的方法是锁。

是最简单的一种锁,只有两种状态:占用和非占用。她适合只能被唯一一个线程独占访问的资源。

信号量 semaphore

允许多个线程并发访问的资源适合使用信号量。一个初始值为N的信号量允许被N个线程并发访问。

当线程访问资源时,信号量的值减1。

如果信号量值=0,则不允许访问共享资源。

访问完资源后,释放信号量,信号量的值+1。

互斥量 mutex

和二元信号量很像,资源仅允许一个线程访问。不同的是信号量可以被任意线程获取释放,也就是说,一个线程获取信号量之后可以被另一个线程释放。而互斥量要求哪个线程获取了互斥量就要由哪个线程释放。

临界区 critical section

临界区和互斥量信号量的区别是,互斥量信号量在任何进程中里都是可见的,也就是说,一个进程创建了互斥量或信号量,另一个进程访问这个互斥量或信号量是合法的。而临界区的作用范围仅限于本进程,其他进程无法获取该锁。

读写锁  read-write lock

使用信号量、互斥量和临界区保证同步,尽管能够保证程序正确,但是对于频繁读偶尔写的操作,效率会很低。读写锁可以解决这个问题。读写锁有两种获取方式,共享的(shared)和独占的(exclusive)。

当锁处于*态的时候,以任何一种方式获取锁都能成功;

当锁处于共享状态时,其他线程以shared方式获取锁会成功,以exclusive方式获取锁,需要等待锁被其他所有线程释放完毕后才能获取。

当锁处于独占状态时,以shared和exclusive方式获取锁都需要等待锁被其他所有线程释放完毕。

读写锁的状态 以shared方式获取 以exclusive方式获取
* 成功 成功
共享 成功 等待
独占 等待 等待

条件变量 condition variable

 对于条件变量,线程有两种操作:等待和唤醒。线程可以等待条件变量,一个条件变量可以被多个线程等待。线程也可以唤醒条件变量,此时所有等待条件变量的线程都将被唤醒。

也就是说,条件变量可以让许多线程一起等待某个某个事件的发生,当某个事件发生时(条件变量被唤醒时),所有线程可以一起恢复执行。