线程之间对资源的竞争:互斥量Mutex 信号灯Semaphore 条件变量Conditions
1. 互斥量Mutex
线程在取出头节点前必须要等待互斥量,如果此时有其他线程已经获得该互斥量,那么该线程将会阻塞在这里.只有等到其他线程释放掉该互斥量后,该线程才有可能得到该互斥量。互斥量从本质上说就是一把锁, 提供对共享资源的保护访问
静态分配的互斥量 :设置为默认的mutex对象PTHREAD_MUTEX_INITIALIZER
动态分配的互斥量,:申请内存(malloc)——>通过pthread_mutex_init进行初始化
调用pthread_mutex_destroy ——> 释放内存(free)
int pthread_mutex_init(pthread_mutex_t 、*mutex,const pthread_mutexattr_t *attr)
int pthread_mutex_destroy(pthread_mutex_t *mutex)
访问共享资源 ——>用互斥量进行加锁——>调用线程会阻塞, 直到互斥量被解锁。
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
返回值: 成功则返回0, 出错则返回错误编号。
trylock是非阻塞调用模式, 如果互斥量没被锁住, trylock函数将对互斥量加锁, 并获得对共享资源的访问权限; 如果互斥量被锁住了,trylock函数将不会阻塞等待而直接返回EBUSY, 表示共享资源处于忙状态
在操作完成后,给互斥量解锁(释放)。这样其他等待该锁的线程才有机会获得该锁,否则其他线程将会永远阻塞。
int pthread_mutex_unlock(pthread_mutex_t *mutex)
互斥量 与 信号量相比
互斥量是一把钥匙,一个人拿了就可以进入一个房间,出来的时候把钥匙交给队列的第一个,信号量是一个可以容纳N人的房间,如果人不满就可以进去,满了,就要等待有人出来。
Binary semaphore与Mutex的差异:
(对于N=1的情况,称为binary semaphore)
1. mutex要由获得锁的线程来释放(谁获得,谁释放)。而semaphore可以由其它线程释放
2. 初始状态可能不一样:mutex的初始值是1 ,semaphore的初始值可能是0(或者为1)
互斥量和信号量的区别
1. 互斥量用于线程的互斥,信号量用于线程的同步。
这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。
互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源
2. 互斥量值只能为0/1,信号量值可以为非负整数。
也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量是,也可以完成一个资源的互斥访问。
3. 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。