函数 pthread_mutex_timelock 函数在线程试图获取一个已加锁的互斥量时,指定线程阻塞时间。若超过时间值,pthread_mutex_timelock 不会对互斥量进行加锁,而是返回错误码 ETIMEDOUT 。
除时间限制外作用同 pthread_mutex_lock 。
#include <pthread.h> #include <time.h> int pthread_mutex_timelock(pthread_mutex_t *restrict mutex, const struct timespec *restrict tsptr); //返回值:若成功,返回0;否则,返回错误编号超时指定愿意等待的 绝对时间 (指示在时间 \(X\) 之前可以阻塞等待)。超时时间用 timespec 结构来表示,用秒和纳秒来描述时间。
10. 读写锁pthread_rwlock_t 为 读写锁(共享互斥锁),它比互斥量允许更高的并行性,适合于对数据结构读的次数远大于写的情况。
读写锁有 3 种状态 :读模式下加锁状态、写模式下加锁状态、不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁。
对于读写锁的 各个状态:
当读写锁是 写加锁 状态时,在此锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞 。
当读写锁是 读加锁 状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是任何希望以写模式对此锁进行加锁的线程都会阻塞。但是当一个线程试图以写模式获取锁时,读写锁会阻塞随后的读模式锁请求,避免读模式锁长期占用 。
读写锁通过 pthread_rwlock_init 函数进行初始化:
#include <pthread.h> int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); //两个函数的返回值:若成功,返回0;否则,返回错误编号也可使用 PTHREAD_RWLOCK_INITIALIZER 常量对静态分配的读写锁进行初始化。
要在读模式下锁定读写锁,需要调用 pthread_rwlock_rdlock ;要在写模式下锁定读写锁,需要调用 pthread_rwlock_wrlock 。不管以何种方式锁住读写锁,都调用 pthread_rwlock_unlock 进行解锁:
#include <pthread.h> int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); //返回值:若成功,返回0;否则,返回错误编号读写锁原语的 条件版本:
#include <pthread.h> int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); //返回值:可以获取锁时,返回0;否则,返回错误EBUSY带有 超时 的读写锁:
#include <pthread.h> #include <time.h> int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict tsptr); int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict tsptr); //返回值:若成功,返回0;若超时,返回 ETIMEOUT 11. 条件变量条件变量 是线程可用的另一种 同步机制 ,条件变量由互斥量保护,允许线程以无竞争的往事等待特定的条件发生 。
条件变量上有两种 基本操作 :
等待:一个线程因等待条件为真而处于等待在条件变量上,此时线程不会占用互斥量(等待条件前要锁住互斥量,等待过程中对互斥量解锁,等待到函数返回(条件改变或超时)后,互斥量再次被锁住)
通知:另一个线程在使条件为真时,通知该条件变量的等待线程(在给等待线程发信号时,不需要占有互斥量)
pthread_cond_t 表示条件变量,初始化 时,可以把常量 PTHREAD_COND_INITIALIZER 赋给静态分配的条件变量,如果条件变量是动态分配的,则需要调用 pthread_cond_init 函数对其进行初始化:
#include <pthread.h> int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); int pthread_cond_destroy(pthread_cond_t *cond); //返回值:若成功,返回0;否则,返回错误编号使用 pthread_cond_wait 等待条件变量为真:
#include <pthread.h> int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict tsptr); //返回值:若成功,返回0;否则,返回错误编号有两个函数可以用于通知线程条件已经满足。pthread_cond_signal 函数至少能唤醒一个等待该条件的线程,而 pthread_cond_broadcast 函数则能唤醒等待该条件的所有线程:
#include <pthread.h> int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond); //返回值:若成功,返回0;否则,返回错误编号 12. 自旋锁