写在最前面

华清远见教育集团
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;
}
linux@linux:~/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;
}

linux@linux:~/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;
}
linux@linux:~/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;
}
linux@linux:~/homework/demo$ gcc test4.c -o test4 -lpthread