1. 什么是读写锁
读写锁是一种与互斥量类似的锁,它允许更高的并行性,具有写独占,读共享的特点。读写锁总共有三种状态:
- 读模式下加锁状态(读锁)
- 写模式下加锁状态(写锁)
- 不加锁状态
读写锁,所谓读共享写独占是指,加读锁的时候,可以多线程一块读,但是不能写;加写锁的时候,不能读,只有当前线程可以写。并且写优先级高于读。读写锁是一把锁,有上面三种状态。
- 读写锁是写模式加锁的时候,解锁前,所有对该锁加锁的线程都会被阻塞;
- 读写锁是读模式加锁的时候,如果线程以读模式对其加锁会成功;如果线程以写模式加锁会阻塞;
- 读写锁是读模式加锁时,既有试图以写模式加锁的线程,又有以读模式加锁的线程,那么读写锁会阻塞随后的读模式加锁请求,优先满足写模式加锁。读锁写锁并行阻塞,写锁优先级高,也就是说线程1持有写锁,线程2请求写锁的同时线程3请求读锁(如果没有写锁申请,那么读锁加锁成功),这时候线程2和3都阻塞,线程1释放锁后,优先满足线程2写锁。
读写锁也叫做共享-独占锁,当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的,也就是所谓的写独占,读共享。读写锁适用于对数据结构读的次数远大于写的情况,因为多线程加读锁的时候可以同时读,效率更高。
2. 读写锁相关API
2.1 读写锁的初始化与释放
- 头文件及函数原型
#include <pthread.h> int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
- 函数描述
- The pthread_rwlock_destroy() function shall destroy the read-write lock object referenced by rwlock and release any resources used by the lock.
- The pthread_rwlock_init() function shall allocate any resources required to use the read-write lock referenced by rwlock and initializes the lock to an unlocked state with attributes referenced by attr.
- 函数参数
- 函数返回值
If successful, the pthread_rwlock_destroy() and pthread_rwlock_init() functions shall return zero; otherwise, an error number shall be returned to indicate the error.
2.2 加读锁
- 头文件及函数原型
#include <pthread.h> int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
- 函数描述
- The pthread_rwlock_rdlock() function shall apply a read lock to the read-write lock referenced by rwlock.
- The pthread_rwlock_tryrdlock() function shall apply a read lock as in the pthread_rwlock_rdlock() function, with the exception that the function shall fail if the equivalent pthread_rwlock_rdlock() call would have blocked the calling thread.
- 函数参数
- 函数返回值
- If successful, the pthread_rwlock_rdlock() function shall return zero; otherwise, an error number shall be returned to indicate the error.
- The pthread_rwlock_tryrdlock() function shall return zero if the lock for reading on the read-write lock object referenced by rwlock is acquired. Otherwise, an error number shall be returned to indicate the error.
2.3 加写锁
- 头文件及函数原型
#include <pthread.h> int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
- 函数描述
The pthread_rwlock_trywrlock() function shall apply a write lock like the pthread_rwlock_wrlock() function, with the exception that the function shall fail if any thread currently holds rwlock (for reading or writing). - 函数参数
- 函数返回值
- The pthread_rwlock_trywrlock() function shall return zero if the lock for writing on the read-write lock object referenced by rwlock is acquired. Otherwise, an error number shall be returned to indicate the error.
- If successful, the pthread_rwlock_wrlock() function shall return zero; otherwise, an error number shall be returned to indicate the error.
2.4 释放锁
- 头文件及函数原型
#include <pthread.h> int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
- 函数描述
The pthread_rwlock_unlock() function shall release a lock held on the read-write lock object referenced by rwlock. - 函数参数
- 函数返回值
If successful, the pthread_rwlock_unlock() function shall return zero; otherwise, an error number shall be returned to indicate the error.
3. 案例分析
#include <stdio.h> #include <unistd.h> #include <pthread.h> pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; int gdata = 100; void* read_th(void* arg) { while(1) { pthread_rwlock_rdlock(&rwlock); printf("read thread: %s, tid: %d, gdata: %d\n", __FUNCTION__, pthread_self(), gdata); usleep(8000); pthread_rwlock_unlock(&rwlock); usleep(6000); } } void* write_th(void* arg) { while(1) { pthread_rwlock_wrlock(&rwlock); printf("write thread: %s, tid: %d, gdata: %d\n", __FUNCTION__, pthread_self(), ++gdata); usleep(8000); pthread_rwlock_unlock(&rwlock); usleep(9000); } } int main(int argc, char* argv[]) { pthread_t tid[6]; for(i = 0; i < 4; i++) { pthread_create(&tid[i], NULL, read_th, NULL); } for(; i< 6; i++) { pthread_join(&tid[i], NULL, write_th, NULL); } for(i = 0; i < 6; i++) { pthread_join(tid[i], NULL); } return 0; }