读写锁
- 什么是读写锁:
读写锁是从互斥锁中发展下来的,读写锁将访问中的读操作和写操作区分开来对待,把对资源的共享者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。在某些读数据比改数据频繁的应用中,读写锁将会比互斥锁表现出很大的优越性。
- 读写锁遵循的规则:
1)只要没有进程持有某个给定的读写锁用于写,那么任意数目的线程都可持有该读写锁用于读。
2)仅当没有线程持有某个给定的读写锁用于读或写,才能分配该读写锁用于写。
3)如果读写锁当前没有读者,也没有写者,那么写者可以立刻获得读写锁,如果读写锁没有写者,那么读者可以立即获得该读写锁。
- 读写锁的声明:
pthread_rwlock_t rwlock;
- 读写锁的初始化:
pthread_rwlock_init (&rwlock,NULL);
- 为读进程获得锁:
pthread_rwlock_rdlock(pthread_rwlock_t *lock);
- 为写进程获得锁:
pthread_rwlock_wrlock(pthread_rwlock_t *lock);
- 读写进程解锁:
pthread_rwlock_unlock(pthread_rwlock_t *lock);
- 读写锁的销毁:
pthread_rwlock_destroy(pthread_rwlock_t *lock);
- 实验一:使用读写锁实现两个线程之间的互斥
#include <stdio.h>
#include <pthread.h>
pthread_rwlock_t rwlock;
int CountReader = 0;
int CountWriter = 0;
void *read(){
printf("this is read thread\n");
/*读加锁*/
pthread_rwlock_rdlock(&rwlock);
CountReader++;
printf("reader start reading\n");
printf("finish read\n");
CountReader--;
if(CountReader == 0){
/*没有读者在进行操作,解锁*/
pthread_rwlock_unlock(&rwlock);
}
}
void *write(){
printf("this is write thread\n");
pthread_rwlock_wrlock(&rwlock);
CountWriter++;
printf("writer start writing\n");
printf("finish write\n");
CountWriter--;
if(CountWriter == 0){
pthread_rwlock_unlock(&rwlock);
}
}
int main()
{
// 创建两个线程实现一个线程读文件,一个线程写文件
pthread_t tid[2];
pthread_rwlock_init(&rwlock, NULL);
pthread_create(&tid[0], NULL, read, NULL);
pthread_create(&tid[1], NULL, write, NULL);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_rwlock_destroy(&rwlock);
return 0;
}
实验结果:
由实验结果我们可以看出,当写操作执行结束,释放了读写锁之后,才进行的读操作。因此我们通过读写锁实现了两个线程之间的互斥。
- 实验二:两个读线程,两个写线程
#include <stdio.h>
#include <pthread.h>
pthread_rwlock_t rwlock;
int CountReader = 0;
int CountWriter = 0;
void *read(void *arg){
char *pthr_name = (char *)arg;
/*读加锁*/
pthread_rwlock_rdlock(&rwlock);
/*执行读操作*/
printf("%s is reading\n",pthr_name);
sleep(2);
printf("%s finish read\n",pthr_name);
/*解锁*/
pthread_rwlock_unlock(&rwlock);
}
void *write(void *arg){
char *pthr_name = (char *)arg;
/*写加锁*/
pthread_rwlock_wrlock(&rwlock);
/*执行写操作*/
printf("%s is writing\n",pthr_name);
sleep(2);
printf("%s finish write\n",pthr_name);
/*解锁*/
pthread_rwlock_unlock(&rwlock);
}
int main()
{
pthread_t read_1;
pthread_t read_2;
pthread_t write_1;
pthread_t write_2;
pthread_rwlock_init(&rwlock, NULL);
/*创建两个读线程read_1 read_2,两个写线程write_1 write_2*/
pthread_create(&read_1, NULL, read, "read_1");
pthread_create(&read_2, NULL, read, "read_2");
pthread_create(&write_1, NULL, write, "write_1");
pthread_create(&write_2, NULL, write, "write_2");
pthread_join(read_1, NULL);
pthread_join(read_2, NULL);
pthread_join(write_1, NULL);
pthread_join(write_2, NULL);
pthread_rwlock_destroy(&rwlock);
return 0;
}
实验结果:
实验结果说明:
由结果我们可以看出,即使在进程进行过程中sleep了两秒,写进程write_1和write_2都是互不干扰的,write_2执行结束之后才执行write_1。我们明显可以看出读进程是不同的,read_1和read_2几乎在同时进行。这个实验也验证了我们之前所讲的,写进程只能有一个在进行,而读进程却可以同时进行多个。