1. 程式人生 > >多執行緒程式設計——讀寫鎖

多執行緒程式設計——讀寫鎖

一、什麼是讀寫鎖

讀寫鎖(也叫共享-獨佔鎖)實際是一種特殊的自旋鎖,它把對共享資源的訪問者劃分成讀者和寫者,讀者只對共享資源進行讀訪問,寫者則需要對共享資源進行寫操作。這種鎖相對於自旋鎖而言,能提高併發性,因為在多處理器系統中,它允許同時有多個讀者來訪問共享資源,最大可能的讀者數為實際的邏輯CPU數。寫者是排他性的,一個讀寫鎖同時只能有一個寫者多個讀者(與CPU數相關),但不能同時既有讀者又有寫者

如果讀寫鎖當前沒有讀者,也沒有寫者,那麼寫者可以立刻獲得讀寫鎖,否則它必須“自旋”在那裡,直到沒有任何寫者或讀者。如果讀寫鎖沒有寫者,那麼讀者可以立即獲得該讀寫鎖,否則讀者必須“自旋”在那裡,直到寫者釋放該讀寫鎖。讀寫鎖適合於對資料結構的讀次數比寫次數多很多的場合。


二、示例程式碼

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
/* 執行緒控制塊 */
static pthread_t reader1;
static pthread_t reader2;
static pthread_t writer1;
/* 共享資料book */
static int book = 0;
/* 讀寫鎖 */
static pthread_rwlock_t rwlock;
/* 函式結果檢查 */
static void check_result(char* str,int result)
{
	if (0 == result)
	{
		printf("%s successfully!\n",str);
	}
	else
	{
		printf("%s failed! error code is %d\n",str,result);
	}
}
/*執行緒入口*/
static void* reader1_entry(void* parameter)
{
	int i = 0;
	//pthread_detach(pthread_self());
	while (1)
	{
		if(i++%5<2)//讀2秒,停3秒。讓寫可獲得鎖,否則讀執行緒一直鎖著,將無法寫
		{
			pthread_rwlock_rdlock(&rwlock); /* 嘗試讀鎖定該讀寫鎖 */
			printf("reader1 read book value is %d\n",book);
			sleep(1); /* 執行緒休眠2秒,切換到其他執行緒執行 */
			pthread_rwlock_unlock(&rwlock); /* 執行緒執行後對讀寫鎖解鎖 */
		}else
		{
			sleep(1);
		}
	}
}
static void* reader2_entry(void* parameter)
{
	int i = 0;
	//pthread_detach(pthread_self());
	while (1)
	{
		if(i++%5<2)
		{
			pthread_rwlock_rdlock(&rwlock); /* 嘗試讀鎖定該讀寫鎖 */
			printf("reader2 read book value is %d\n",book);
			sleep(1); /* 執行緒休眠2秒,切換到其他執行緒執行 */
			pthread_rwlock_unlock(&rwlock); /* 執行緒執行後對讀寫鎖解鎖 */
		}else
		{
			sleep(1); /* 執行緒休眠2秒,切換到其他執行緒執行 */
		}
	}
}
static void* writer1_entry(void* parameter)
{
	//pthread_detach(pthread_self());
	while (1)
	{
		//printf("writer1 \r\n");
		if(!pthread_rwlock_trywrlock(&rwlock)) /* 嘗試寫鎖定該讀寫鎖 */
		{
			book++;
			printf("writer1 write book value is %d\n",book);
			pthread_rwlock_unlock(&rwlock); /* 對讀寫鎖解鎖 */
			sleep(1); /* 執行緒休眠2秒,切換到其他執行緒執行 */
		}else
		{
			printf("Be BUSY ,can`t write now\r\n");
			sleep(1);
		}
	}
}
/* 使用者應用入口 */
int application_init()
{
	int result;
	/* 預設屬性初始化讀寫鎖 */
	pthread_rwlock_init(&rwlock,NULL);
	/*建立writer1執行緒,執行緒入口是writer1_entry, 執行緒屬性為,入口引數為NULL*/
	result = pthread_create(&writer1,NULL,writer1_entry,NULL);
	check_result("writer1 created",result);
	/*建立reader1執行緒,執行緒入口是reader1_entry, 執行緒屬性為預設值,入口引數為NULL*/
	result = pthread_create(&reader1,NULL,reader1_entry,NULL);
	check_result("reader1 created",result);
	/*建立reader2執行緒,執行緒入口是reader2_entry, 執行緒屬性為預設值,入口引數為NULL*/
	result = pthread_create(&reader2,NULL,reader2_entry,NULL);
	check_result("reader2 created",result);
	
	
	return 0;
}
int main()
{
	int i ;
	application_init();
	i=100;
	do{
		sleep(1);
	}while(i--);
}

執行結果:

-bash-3.2$ !g
gcc -pthread rwlock.c -o app
-bash-3.2$ ./app
writer1 created successfully!
reader1 created successfully!
reader2 created successfully!
writer1 write book value is 1
reader1 read book value is 1
reader2 read book value is 1
Be BUSY ,cant write now
reader1 read book value is 1
reader2 read book value is 1
Be BUSY ,cant write now
writer1 write book value is 2
writer1 write book value is 3
reader2 read book value is 3
reader1 read book value is 3
Be BUSY ,cant write now
reader2 read book value is 3
reader1 read book value is 3
Be BUSY ,cant write now
writer1 write book value is 4
writer1 write book value is 5
writer1 write book value is 6
reader2 read book value is 6
reader1 read book value is 6
Be BUSY ,cant write now
reader2 read book value is 6
reader1 read book value is 6
Be BUSY ,cant write now
writer1 write book value is 7
writer1 write book value is 8
writer1 write book value is 9
reader2 read book value is 9
Be BUSY ,can`t write now
reader1 read book value is 9