读写锁
- 什么是读写锁:
读写锁是从互斥锁中发展下来的,读写锁将访问中的读操作和写操作区分开来对待,把对资源的共享者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。在某些读数据比改数据频繁的应用中,读写锁将会比互斥锁表现出很大的优越性。
- 读写锁遵循的规则:
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几乎在同时进行。这个实验也验证了我们之前所讲的,写进程只能有一个在进行,而读进程却可以同时进行多个。