【版权申明】转载请附上出处链接
Linux线程中的互斥锁与条件变量
1. 互斥锁
互斥锁用于保护临界区资源(实际保护的是临界区中被操纵的数据),通常用于保护多个线程间的共享数据。而这些共享数据通常是一些可供线程间使用的全局变量/硬件寄存器等,为达到线程安全的目的,我们需要保证在任何时刻只有一个线程在执行其中的代码。
故互斥锁只有两个状态,即“上锁”和“未上锁”。
互斥锁常见函数:
// 头文件
#include <pthread.h>
/* Initialize a mutex. */
int pthread_mutex_init (pthread_mutex_t *__mutex);
/* Destroy a mutex. */
int pthread_mutex_destroy (pthread_mutex_t *__mutex);
/* Try locking a mutex. */
int pthread_mutex_trylock (pthread_mutex_t *__mutex);
/* Lock a mutex. */
int pthread_mutex_lock (pthread_mutex_t *__mutex);
/* Unlock a mutex. */
int pthread_mutex_unlock (pthread_mutex_t *__mutex);
#ifdef __USE_XOPEN2K
/* Wait until lock becomes available, or specified time passes. */
extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
const struct timespec *__restrict __abstime);
#endif
互斥锁缺点:
-
当使用pthread_mutex_lock()函数来进行上锁动作时,如果互斥锁已经被其他线程占用了,那么该线程将会在原地打转(不断消耗CPU分配下来的时间片直到该线程获得互斥锁),这非常消耗CPU资源并且该线程没办法做其他事情;
-
当使用pthread_mutex_trylock()函数来尝试上锁时,不论获得锁与否立刻返回。
若获得锁,则接着往下执行;
若没有获得锁,则进行其他操作,过会再去尝试获得锁来访问临界区。但如果接下来的操作需要用到临界区的资源或者等待临界区资源就绪,只能原地打转等待资源就绪。
所以,条件变量的出现就弥补了互斥锁缺点,使得CPU的资源得到更合理的使用。
当我们线程需要访问临界区时,应当先上锁(mutex)再查看条件变量(cond)是否满足:
当条件满足时,我们继续往下执行,此时的数据正是我们想要的;
当条件不满足时,我们释放互斥锁并进入休眠(释放CPU分配给我们的时间片,让其他线程使用),等待其他线程使得条件满足并发出信号唤醒我们。
2. 条件变量
/* Initialize condition variable COND using attributes ATTR, or use
the default values if later is NULL. */
extern int pthread_cond_init (pthread_cond_t *__restrict __cond,
const pthread_condattr_t *__restrict __cond_attr);
/* Destroy condition variable COND. */
extern int pthread_cond_destroy (pthread_cond_t *__cond);
/* Wake up one thread waiting for condition variable COND. */
extern int pthread_cond_signal (pthread_cond_t *__cond);
/* Wake up all threads waiting for condition variables COND. */
extern int pthread_cond_broadcast (pthread_cond_t *__cond);
/* Wait for condition variable COND to be signaled or broadcast.
MUTEX is assumed to be locked before.
This function is a cancellation point and therefore not marked with
__THROW. */
extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
pthread_mutex_t *__restrict __mutex);
/* Wait for condition variable COND to be signaled or broadcast until
ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an
absolute time specification; zero is the beginning of the epoch
(00:00:00 GMT, January 1, 1970).
This function is a cancellation point and therefore not marked with
__THROW. */
extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
pthread_mutex_t *__restrict __mutex,
const struct timespec *__restrict __abstime);