Linux下的多线程编程——同步互斥问题(读写锁)

读写锁

  • 什么是读写锁:

读写锁是从互斥锁中发展下来的,读写锁将访问中的读操作和写操作区分开来对待,把对资源的共享者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。在某些读数据比改数据频繁的应用中,读写锁将会比互斥锁表现出很大的优越性。

  • 读写锁遵循的规则:

    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几乎在同时进行。这个实验也验证了我们之前所讲的,写进程只能有一个在进行,而读进程却可以同时进行多个。

猜你喜欢

转载自blog.csdn.net/zhao_yuting/article/details/79936201