线程间的同步互斥学习
写在最前面
华清远见教育集团
15年专注高端IT培训
做良心教育,做专业教育,做受人尊敬的职业教育创客学院官网:http://www.makeru.com.cn/
华清远见创客学院嵌入式课程链接:http://www.makeru.com.cn/emb
华清远见创客学院物联网课程链接:http://www.makeru.com.cn/iot
正文
个人认为各个线程执行的任务有所不同,但是本质上都是对数据的处理,而数据脱离了项目去分析好像没有啥意义。同时,多个线程共享一些全局资源。为了避免不同线程对资源读写造成的冲突,那我们就要引入同步互斥机制。本文重点还是学习这些方法。
对于临界资源的访问,有同步机制和互斥机制两种
线程同步机制
- 信号量(多个)
- 条件变量+互斥锁
线程互斥机制
- 信号量(单个)
- 互斥锁
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