一、读写锁原理
在实际问题中,互斥锁可以解决大部分互斥的问题,保证资源可以被独占式使用,但是有时候互斥锁可能会导致效率降低。比如:系统中有成千上万条线程对同一资源进行访问,其中绝大部分是对其进行读取,只有少部分线程需要对其进行写入,这样使用互斥锁效率就会很低,所以使用读写锁。
读锁:获取数据( read、printf、fread、fget、get、getchar、scanf),当一个线程上了读锁,其他线程可以一直上读锁。
写锁:修改数据(write、puts、fwrite、fputs、putchar)当一个线程上了写锁,后面的其他线程读、写都不能上,直到解了第一个写锁。
二、读写锁对对应的API
1、初始化读写锁
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);
attr:锁的属性一般设置为NULL
返回值:成功返回0,失败返回非0
静态初始化读写锁: pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
代码段:
pthread_rwlock_t rwl; int pthread_rwlock_init_ret = pthread_rwlock_init(&rwl, NULL); if (pthread_rwlock_init_ret != 0) { perror("pthread_rwlock_init"); exit(-1); } else { printf("读写锁初始化成功!\n"); }
2、读锁、写锁、销毁读写锁
读锁:int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
写锁:int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
销毁读写锁:int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
代码段:验证上了写锁后只有在解了写锁才能再上读锁
#include <stdio.h> #include <errno.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> pthread_rwlock_t rwl; void *Pthread_Task(void *arg) { if ((long)arg == 1) { printf("我是第%ld号线程,我要上写锁\n", (long)arg); int pthread_rwlock_rdlock_ret = pthread_rwlock_wrlock(&rwl); if (pthread_rwlock_rdlock_ret != 0) { perror("pthread_rwlock_rdlock"); exit(-1); } else { printf("我是%ld号线程,我上写锁成功!3s之后我解写锁\n", (long)arg); sleep(3); int pthread_rwlock_unlock_ret = pthread_rwlock_unlock(&rwl); if(pthread_rwlock_unlock_ret != 0) { perror("pthread_rwlock_unlock"); exit(-1); } else { printf("解写锁成功!\n"); } } } if ((long)arg == 2) { printf("我是第%ld号线程,我要上读锁\n", (long)arg); int pthread_rwlock_rdlock_ret = pthread_rwlock_rdlock(&rwl); if (pthread_rwlock_rdlock_ret != 0) { perror("pthread_rwlock_rdlock"); exit(-1); } else { printf("我是%ld号线程,我上读锁成功!\n", (long)arg); } } pthread_exit(NULL); } int main() { int pthread_rwlock_init_ret = pthread_rwlock_init(&rwl, NULL); if (pthread_rwlock_init_ret != 0) { perror("pthread_rwlock_init"); exit(-1); } else { printf("读写锁初始化成功!\n"); } pthread_t pid1, pid2; pthread_create(&pid1, NULL, Pthread_Task, (void *)1); sleep(1); pthread_create(&pid2, NULL, Pthread_Task, (void *)2); pause(); }
代码实现效果: