Mutex是mutual exclusion的缩写,即互斥。互斥量是线程间同步和同时对共享内存写数据时做保护的主要方法之一。
互斥量就像一把对共享资源访问时进行保护的锁。Pthreads中规定某个时刻只有一个线程能够拥有某个互斥量(或者说对该互斥量上锁),因此即使有多个线程尝试同时对某个互斥量上锁,只有一个线程会成功;此时只有该线程释放了互斥量后,其他的线程才有可能持有互斥量。由此使得每个线程轮流访问被保护的数据。
互斥量可用于防止“竞争”的发生,下面是一个有关银行交易的竞争示例。
线程1 |
线程2 |
存款 |
获取存款:1000元 |
1000元 | |
获取存款:1000元 |
1000元 | |
存款200元 |
1000元 | |
存款200元 |
1000元 | |
更新存款:1000+200元 |
1200元 | |
更新存款:1000+200元 |
1200元 |
这里由于发生了竞争,使得实际上的存款应该为1400元,但得到了1200元的结果。因此当一个线程在使用共享数据(存款)时,需要用互斥量加锁保护。
我们经常在对全局变量操作时使用互斥量,考虑到可能有多个线程同时对全局变量操作,这是一种最安全的方式,可以确保全局变量的正确更新。我们也把更新全局变量操作的代码段称为临界区(critical section)。
使用互斥量的流程如下:
- 创建并初始化互斥量
- 一些线程尝试对互斥量加锁
- 只有一个线程能够成功加锁
- 成功加锁的线程执行一些操作
- 成功加锁的线程释放互斥量
- 其他的线程获得互斥量并加锁,重复上述操作
- 完成相关操作,互斥量被销毁
当一些线程同时竞争加锁某个互斥量时,该调用是阻塞的,即没有获得互斥量的线程会阻塞住。当然也有不阻塞的方法,此时线程会尝试获取互斥量,无论是否获取到都会直接返回。
注意需要由编程人员确保每个线程通过使用互斥量实现对共享数据的保护,例如如果有4的线程同时更新某个数据,但是只有一个线程使用了互斥量,那么数据仍有被意外修改的可能。