線程同步的一種實現

    爲使系統中的多線程能有條不紊地運行,在系統中必須提供用於實現線程間同步和通信的機制。爲了支持不同頻率的交互操作和不同程度的並行性,在多線程OS中通常提供多種同步機制,如互斥鎖、條件變量、計數信號量以及多讀、單寫鎖等,下面就以互斥鎖爲例實現線程同步。

    其中, 程序中有兩個線程,A、B , 線程A是主線程,主要負責讀取用戶從終端中輸入的字符串;而線程B是新建的線程,主要用於判斷讀取的字符串是否爲結束符,如果不是,則向終端打印出剛纔輸入的字符串的長度並等待再次輸入,否則結束程序。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>

void *thread_function(void *arg);
pthread_mutex_t work_mutex;
int time_to_exit=0; /*互斥量,保護工作區及額外變量time_to_exit*/

#define WORK_SIZE 1024
char work_area[WORK_SIZE]; /*工作區*/

int main()
{
	int res ;
	pthread_t a_thread;
	void *thread_result;
	res = pthread_mutex_init(&work_mutex,NULL); /*初始化工作區*/
	if(res!=0){
		perror("Mutex initialization failed");
		exit(EXIT_FAILURE);
	}
	res = pthread_create(&a_thread,NULL,thread_function,NULL); /*創建新線程*/
	if(res!=0){
		perror("Thread creation failed");
		exit(EXIT_FAILURE);
	}
	/*主線程A*/
	pthread_mutex_lock(&work_mutex);	//主線程對互斥量加鎖
	printf("Input some text. Enter 'end' to finish\n");
	while(!time_to_exit){//當線程B遇到結束符後會將變量置爲非零以結束循環
		fgets(work_area,WORK_SIZE,stdin);	//從終端向工作區中輸入字符串
		pthread_mutex_unlock(&work_mutex);	//解鎖互斥量
		while(1){
			pthread_mutex_lock(&work_mutex);			// 這裏必須等待線程B釋放後才能加鎖,否則只能一直等待
			if(work_area[0]!='\0'){						 
				pthread_mutex_unlock(&work_mutex);	 
				sleep(1);								
			}else{
				break;
			}
		}
	}
	pthread_mutex_unlock(&work_mutex);
	printf("\nWaiting for thread to finish...\n");
	res = pthread_join(a_thread,&thread_result);	//父線程等待子線程終止
	if(res!=0){
		perror("Thread join failed");
		exit(EXIT_FAILURE);
	}
	printf("Thread joined\n");
	pthread_mutex_destroy(&work_mutex);
	exit(EXIT_SUCCESS);
}

/*新線程B*/
void *thread_function(void *arg)
{
	sleep(1);
	pthread_mutex_lock(&work_mutex);//等待線程A讀取字符串並解鎖後將互斥量加鎖,以獲取工作區資源
	while(strncmp("end",work_area,3)!=0){//判斷是否遇到結束符end
		printf("You input %d characters\n",strlen(work_area)-1);
		work_area[0]='\0';
		pthread_mutex_unlock(&work_mutex);
		sleep(1);
		pthread_mutex_lock(&work_mutex);
		while(work_area[0]=='\0'){//通過將第一個字符設置爲NULL,通知線程A已完成字符統計
			pthread_mutex_unlock(&work_mutex);//解鎖互斥量並等待線程A繼續運行
			sleep(1);
			pthread_mutex_lock(&work_mutex);
		}
	}
	time_to_exit = 1;
	work_area[0] = '\0' ;
	pthread_mutex_unlock(&work_mutex);
	pthread_exit(0);
}


在該程序中,新線程首先試圖對互斥量加鎖。如果它已經被加鎖,這個調用將被阻塞直到鎖被釋放爲止。一旦獲得訪問權,新線程將檢查是否有申請退出程序的請求。如果有,就簡單設置time_to_exit變量,再把工作區的第一個字符設置爲'\0',然後退出。如果不想退出,就對字符個數進行統計。然後把work_area數組中的第一個字符設置爲'\0'。通過將第一個字符設置爲NULL,通知線程A已完成字符統計。隨後解鎖互斥量並等待主線程繼續運行。程序將週期性地嘗試給互斥量加鎖,如加鎖成功,則檢查主線程是否又有字符串需要統計。如沒有,則解鎖互斥量繼續等待;否則將統計字符個數,並再次進入循環。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章