1. 程式人生 > >執行緒間的同步互斥學習

執行緒間的同步互斥學習

寫在最前面

華清遠見教育集團
15年專注高階IT培訓
做良心教育,做專業教育,做受人尊敬的職業教育

創客學院官網:http://www.makeru.com.cn/
華清遠見創客學院嵌入式課程連結:http://www.makeru.com.cn/emb
華清遠見創客學院物聯網課程連結:http://www.makeru.com.cn/iot

 

正文

 

個人認為各個執行緒執行的任務有所不同,但是本質上都是對資料的處理,而資料脫離了專案去分析好像沒有啥意義。同時,多個執行緒共享一些全域性資源。為了避免不同執行緒對資源讀寫造成的衝突,那我們就要引入同步互斥機制。本文重點還是學習這些方法。
 

對於臨界資源的訪問,有同步機制和互斥機制兩種

執行緒同步機制

  1. 訊號量(多個)
  2. 條件變數+互斥鎖

執行緒互斥機制

  1. 訊號量(單個)
  2. 互斥鎖

 

 

1.訊號量實現同步

#include<stdio.h>
#include <pthread.h>
#include <semaphore.h>


#define N 64
typedef struct message{
	char buf[N];
	int len;
}msg_t;

sem_t sem_reverse;
sem_t sem_printf;

void* reverse_msgbuf(void* arg)
{
	msg_t *msg = (msg_t *)arg;
	int i = 0;
	char tmp;
	while(1){
		sem_wait(&sem_reverse);	//P操作 sem_reverse 申請資源(資源數減少1)
		printf("reverse_msgbuf -------------\n");
			//printf("hello reverse_msgbuf.\n");
#if 1
			for(i = 0; i < msg->len/2; i ++){
				tmp			 = msg->buf[i];
				msg->buf[i]  = msg->buf[msg->len - i - 1];
				msg->buf[msg->len - i -1] = tmp;
			}
#endif 
			sleep(1);
			printf("reverse_msgbuf :%s\n",msg->buf);
		sem_post(&sem_printf);	//V操作 sem_printf 釋放資源(資源數加1)
	}
}

void* printf_msgbuf(void* arg)
{
	msg_t *msg = (msg_t *)arg;
	while(1){
		sem_wait(&sem_printf);	//P操作 sem_printf 申請資源(資源數減少1)
			printf("printf_msgbuf :***********\n");
			printf("printf_msgbuf :%s\n",msg->buf);
		sem_post(&sem_reverse);	//V操作 sem_reverse 釋放資源(資源數加1)
	}
}

int main(int argc, const char *argv[])
{
	msg_t msg = {"123456789",9};
	pthread_t tid[2];

	sem_init(&sem_reverse,0,1);		//申請訊號量 sem_reverse 資源數 1
	sem_init(&sem_printf,0,0);		//申請訊號量 sem_printf 資源數 1
	pthread_create(&tid[0],NULL,reverse_msgbuf,(void *)&msg);	//申請執行緒 reverse_msgbuf
	pthread_create(&tid[1],NULL,printf_msgbuf,(void *)&msg);

	pause();

	return 0;
}
[email protected]:~/homework/demo$ gcc test1.c -o test1 -lpthread 

 

 

2.互斥鎖實現互斥

#include<stdio.h>
#include <pthread.h>

#define N 64
typedef struct message{
	char buf[N];
	int len;
}msg_t;

pthread_mutex_t mymutex;

void* reverse_msgbuf(void* arg)
{
	msg_t *msg = (msg_t *)arg;
	int i = 0;
	char tmp;
	while(1){
		pthread_mutex_lock(&mymutex);
			for(i = 0; i < msg->len/2; i ++){
				tmp			 = msg->buf[i];
				msg->buf[i]  = msg->buf[msg->len - i - 1];
				msg->buf[msg->len - i -1] = tmp;
			}
		pthread_mutex_unlock(&mymutex);
	}
}

void* printf_msgbuf(void* arg)
{
	msg_t *msg = (msg_t *)arg;
	while(1){
			pthread_mutex_lock(&mymutex);	//加鎖
			printf("buf :%s\n",msg->buf);
			pthread_mutex_unlock(&mymutex);	//解鎖
		sleep(1);
	}
}

int main(int argc, const char *argv[])
{
	msg_t msg = {"123456789",9};

	pthread_t tid[2];
	pthread_mutex_init(&mymutex,NULL);	//申請鎖 mymutex
	
	pthread_create(&tid[0],NULL,reverse_msgbuf,(void *)&msg);	//申請執行緒 reverse_msgbuf
	pthread_create(&tid[1],NULL,printf_msgbuf,(void *)&msg);

	pause();

	return 0;
}

[email protected]:~/homework/demo$ gcc test2.c -o test2 -lpthread 

 

 

3.條件鎖實現同步 "pthread_cond_broadcast 喚醒"

#include<stdio.h>
#include <pthread.h>

#define N 64
typedef struct message{
	char buf[N];
	int len;
//	int busy_flag;
}msg_t;

int flag = 0;
pthread_mutex_t mymutex;
pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;

void* reverse_msgbuf(void* arg)
{
	msg_t *msg = (msg_t *)arg;
	int i = 0;
	char tmp;
	while(1){
		pthread_mutex_lock(&mymutex);
		printf("reverse_msgbuf -------------\n");
		while(flag != 0){
			pthread_cond_wait(&mycond,&mymutex);		//解鎖互斥鎖,執行緒阻塞
		}
			//printf("hello reverse_msgbuf.\n");
#if 1
			for(i = 0; i < msg->len/2; i ++){
				tmp			 = msg->buf[i];
				msg->buf[i]  = msg->buf[msg->len - i - 1];
				msg->buf[msg->len - i -1] = tmp;
			}
#endif 
			printf("reverse_msgbuf :%s\n",msg->buf);
			flag = 1;							//更新 flag =1
		pthread_mutex_unlock(&mymutex);
		pthread_cond_broadcast(&mycond);		//通過廣播喚醒另一個執行緒的 pthread_cond_wait
	}
}

void* printf_msgbuf(void* arg)
{
	msg_t *msg = (msg_t *)arg;
	while(1){
			pthread_mutex_lock(&mymutex);
			printf("printf_msgbuf :***********\n");
		while(flag != 1){
			pthread_cond_wait(&mycond,&mymutex);
		}
			printf("printf_msgbuf :%s\n",msg->buf);
			flag = 0;								//更新變數 flag = 0
			pthread_mutex_unlock(&mymutex);
			pthread_cond_broadcast(&mycond);		//通過廣播喚醒另一個執行緒的 pthread_cond_wait
	}
}

int main(int argc, const char *argv[])
{
	//msg_t msg = {"123456789",9,0};
	msg_t msg = {"123456789",9};

	pthread_t tid[2];
	
	pthread_cond_init(&mycond,NULL);	//申請條件鎖
	pthread_mutex_init(&mymutex,NULL);	//申請互斥鎖

	pthread_create(&tid[0],NULL,reverse_msgbuf,(void *)&msg);	//申請執行緒
	pthread_create(&tid[1],NULL,printf_msgbuf,(void *)&msg);	//申請執行緒

	pause();

	return 0;
}
[email protected]:~/homework/demo$ gcc test3.c -o test3 -lpthread 

 

 

 

4.條件鎖實現同步 "pthread_cond_signal 喚醒"

#include<stdio.h>
#include <pthread.h>

#define N 64
typedef struct message{
	char buf[N];
	int len;
	//	int busy_flag;
}msg_t;

pthread_mutex_t mymutex;
pthread_cond_t mycond_reverse = PTHREAD_COND_INITIALIZER;
pthread_cond_t mycond_printf  = PTHREAD_COND_INITIALIZER;

void* reverse_msgbuf(void* arg)
{
	msg_t *msg = (msg_t *)arg;
	int i = 0;
	char tmp;
	while(1){
		pthread_mutex_lock(&mymutex);
		pthread_cond_wait(&mycond_reverse,&mymutex);
		printf("reverse_msgbuf -------------\n");
#if 1
		for(i = 0; i < msg->len/2; i ++){
			tmp			 = msg->buf[i];
			msg->buf[i]  = msg->buf[msg->len - i - 1];
			msg->buf[msg->len - i -1] = tmp;
		}
#endif 
		printf("reverse_msgbuf :%s\n",msg->buf);
		pthread_mutex_unlock(&mymutex);
	}
}

void* printf_msgbuf(void* arg)
{
	msg_t *msg = (msg_t *)arg;
	while(1){
		pthread_mutex_lock(&mymutex);
		pthread_cond_wait(&mycond_printf,&mymutex);
		printf("printf_msgbuf :***********\n");
		printf("printf_msgbuf :%s\n",msg->buf);
		pthread_mutex_unlock(&mymutex);
	}
}

int main(int argc, const char *argv[])
{
	//msg_t msg = {"123456789",9,0};
	msg_t msg = {"123456789",9};

	pthread_t tid[2];

	pthread_cond_init(&mycond_printf,NULL);
	pthread_cond_init(&mycond_reverse,NULL);	//條件鎖
	pthread_mutex_init(&mymutex,NULL);			//互斥鎖

	pthread_create(&tid[0],NULL,reverse_msgbuf,(void *)&msg);
	pthread_create(&tid[1],NULL,printf_msgbuf,(void *)&msg);	//申請執行緒

	while(1){
		pthread_cond_signal (&mycond_printf);		//喚醒 mycond_printf
		sleep(1);	
		pthread_cond_signal (&mycond_reverse);		//喚醒 mycond_reverse
		sleep(1);
	}

	pause();

	return 0;
}
[email protected]:~/homework/demo$ gcc test4.c -o test4 -lpthread