首先介紹下pthread_cond_t。 在Linux下稱之為狀態變量,與之相關的有下面幾個API:
int pthread_cond_init (pthread_cond_t *COND,pthread_condattr_t *cond_ATTR);
int pthread_cond_signal (pthread_cond_t *COND);
int pthread_cond_broadcast (pthread_cond_t *COND);
int pthread_cond_wait (pthread_cond_t *COND, pthread_mutex_t *MUTEX);
int pthread_cond_timedwait (pthread_cond_t *COND, pthread_mutex_t *MUTEX, const struct timespec *ABSTIME);
int pthread_cond_destroy (pthread_cond_t *COND);
這裡就講下2個api,pthread_cond_signal和pthread_cond_wait,一般的用法如下:
{
pthread_mutex_lock(lock)
...
pthread_cond_wait(cond, lock);
...
pthread_cond_mutex_unlock(lock);
}
pthread_cond_wait會解鎖lock,然後在cond上等待,這兩步是atomic operation. 當pthread_cond_wait返回時,會同時對lock上鎖. 這裡我的理解是,如果獲取不到lock鎖,即使cond已經被激活,pthread_cond_wait依然不會返回。
{
pthread_mutex_lock(lock);
...
pthread_cond_signal(cond);
...
pthread_mutex_unlock(lock);
}
pthread_cond_signal調用之前一定會先拿到lock鎖。pthread_cond_signal不會去管lock鎖,只是將cond激活,接下去釋放lock鎖。這時候pthread_cond_wait就可以得到lock從而返回了。
言歸正傳,下面是利用條件變量實現的一個讀寫鎖的例子:
typedef struct pthread_rwlock
{
int active_readers; /* -1 when writer lock locked, >0 when read lock locked */
int pending_readers;
int pending_writers;
pthread_mutex_t mutex;
pthread_cond_t ok_to_read;
pthread_cond_t ok_to_write;
} pthread_rwlock_t ;
int pthread_rwlock_init(pthread_rwlock_t * lock, pthread_rwlockattr_t *attr)
{
active_readers = 0;
pending_readers = 0;
pending_writers = 0;
pthread_mutex_init(&lock->mutex, NULL);
pthread_cond_init(&lock->ok_to_read, NULL);
pthread_cond_init(&lock->ok_to_write, NULL);
return 0;
}
int pthread_rwlock_destroy(pthread_rwlock_t * lock)
{
pthread_mutex_destroy(&lock->mutex);
pthread_cond_destroy(&lock->ok_to_read);
pthread_cond_destroy(&lock->ok_to_write);
return 0;
}
int pthread_rwlock_rdlock(pthread_rwlock_t * lock)
{
pthread_mutex_lock(&lock->mutex);
lock->pending_readers++;
while(lock->active_readers < 0) /* the write lock locked */
pthread_cond_wait(&lock->ok_to_read, &lock->mutex);
lock->pending_readers--;
lock->active_readers++;
pthread_mutex_unlock(&lock->mutex);
return 0;
}
int pthread_rwlock_wrlock(pthread_rwlock_t * lock)
{
pthread_mutex_lock(&lock->mutex);
lock->pending_writers++;
while(lock->active_readers) /* the write lock or read lock locked */
pthread_cond_wait(&lock->ok_to_write, &lock->mutex);
lock->pending_writers--;
lock->active_readers = -1;
pthread_mutex_unlock(&lock->mutex);
return 0;
}
int pthread_rwlock_unlock(pthread_rwlock_t * lock)
{
pthread_mutex_lock(&lock->mutex);
assert(lock->active_readers)
if (lock->active_readers > 0) /* release the read lock */
{
lock->active_readers--;
if (lock->active_readers == 0) /* no read lock locked */
{
pthread_cond_signal(&lock->ok_to_write);
}
} else if (lock->active_readers < 0) /* release the write lock */
{
lock->active_readers=0;
/* it may be different, when write lock has higher priority than read lock */
if (lock->pending_readers > 0) {
pthread_cond_broadcast(&lock->ok_to_read);
} else if (lock->pending_writers > 0) {
pthread_cond_signal(&lock->ok_to_write);
}
}
pthread_mutex_unlock(&lock->mutex);
return 0;
}
還有pthread_rwlock_tryrdlock 和 pthread_rwlock_trywrlock,感興趣的自己寫吧,感覺這兩個用的不多。