当前位置: 首页 > news >正文

0807 IO线程的同步互斥

Part 1.梳理思维导图

一.同步互斥的概念

由于线程之间的数据是共享的,导致多线程访问数据时,线程的光标位置难以确定,故引入同步互斥。

临界资源:多线程访问的资源

互斥:同一时间只能一个线程访问

同步:互斥的基础上,保证了顺序

        2.解决同步互斥的方法

1.互斥锁

2.信号量

3.条件变量

二.互斥锁

        1.理论

将每个临界资源上锁,让线程上锁成功后只能一个线程访问资源,其他线程会阻塞。

解决问题:一个生产者对应一个消费者

        2.pthread_mutex_init

                a.功能

初始化互斥锁

                b.原型

pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;(宏定义方式)

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);

参数:

pthread_mutex_t *mutex:互斥锁的指针

const pthread_mutexattr_t *mutexattr:互斥锁的类型(默认为NULL)

                c.例子
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//宏定义
                d.man手册

man pthread_mutex_init

        3.pthread_mutex_lock

                a.功能

上锁,如果已经被其他线程锁上了,进入阻塞态等待其他线程解锁后再上锁

                b.原型

int pthread_mutex_lock(pthread_mutex_t *mutex);

参数:

pthread_mutex_t *mutex:互斥锁的指针

                c.例子
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *callback1(void *arg)
{		while(1){pthread_mutex_lock(&mutex);//上锁a += 20;printf("a = %d\n",a);}pthread_exit(NULL);
}
                d.man手册

man pthread_mutex_lock

        4.pthread_mutex_unlock

                a.功能

解锁

                b.原型

int pthread_mutex_unlock(pthread_mutex_t *mutex);

参数

pthread_mutex_t *mutex:互斥锁的指针

                c.例子
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *callback1(void *arg)
{		while(1){pthread_mutex_lock(&mutex);a += 20;printf("a = %d\n",a);pthread_mutex_unlock(&mutex);//解锁}pthread_exit(NULL);
}
                d.man手册

man pthread_mutex_unlock

        5.pthread_mutex_destroy

                a.功能

销毁锁

                b.原型

int pthread_mutex_destroy(pthread_mutex_t *mutex);

参数:

pthread_mutex_t *mutex:互斥锁的指针

                c.例子
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *callback1(void *arg)
{		while(1){pthread_mutex_lock(&mutex);a += 20;printf("a = %d\n",a);pthread_mutex_unlock(&mutex);//解锁}pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{pthread_t thread1;if(0 != pthread_create(&thread1,NULL,callback1,NULL)){printf("thread1 pthread_create error\n");return -1;}pthread_join(thread1,NULL);	pthread_mutex_destroy(&mutex);//销毁锁return 0;
}
                d.man手册

man pthread_mutex_destroy

        6.pthread_mutex_trylock

                a.功能

尝试上锁,但是有其他上锁了,不会阻塞线程

                b.原型

int pthread_mutex_trylock(pthread_mutex_t *mutex);

参数:

pthread_mutex_t *mutex:互斥锁的指针

                c.man手册

man pthread_mutex_trylock

三.信号灯

        1.理论

对每一个需要访问临界资源的线程都做一个需要申请的操作

P操作:申请信号值 +1

V操作:释放信号值-1

解决问题:一个生产者对应少量消费者

        2.sem_init

                a.功能

初始化信号量

                b.原型

int sem_init(sem_t *sem, int pshared, unsigned int value);

参数:

sem_t *sem:信号量指针

int pshared:信号量参数:0表示线程共享 非0表示进程共享

unsigned int value:信号量初始化

                c.例子
int main(int argc, const char *argv[])
{sem_t sem;//创建信号量semsem_init(&sem,0,4);//初始化sem
}
                d.man手册

man sem_init

        3.sem_wait(p操作)

                a.功能

信号量大于0,则信号量-1,并允许线程就行访问

信号量等于0,则信号量不变,不允许线程就行访问

                b.原型

int sem_wait(sem_t *sem);

参数:

sem_t *sem:信号量指针

                c.例子
void *callback1(void *arg)
{		while(1){sem_wait(&sem);	//p操作printf("生产\n");sleep(1);}		pthread_exit(NULL);
}
                d.man手册

man sem_wait

        4.sem_post(v操作)

                a.功能

信号量+1,表示线程访问资源结束

                b.原型

int sem_post(sem_t *sem);

参数:

sem_t *sem:信号量指针

                c.例子
void *callback1(void *arg)
{		while(1){sem_wait(&sem);	printf("生产\n");sleep(1);sem_post(&sem);}		pthread_exit(NULL);
}
                d.man手册

man sem_post

        5.sem_destroy

                a.功能

销毁信号量

                b.原型

int sem_destroy(sem_t *sem);

参数:

sem_t *sem:信号量指针

                c.例子
#include<myhead.h>sem_t sem;void *callback1(void *arg)
{		while(1){sem_wait(&sem);	printf("生产\n");sleep(1);sem_post(&sem);}		pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{pthread_t thread1;sem_init(&sem,0,1);if(0 != pthread_create(&thread1,NULL,callback1,NULL)){printf("thread1 pthread_create error\n");return -1;}pthread_join(thread1,NULL);	sem_destroy(&sem);//销毁信号值return 0;
}
                d.man手册

man sem_destroy

        6.sem_getvalue

                a.功能

获取信号量的值

                b.原型

int sem_getvalue(sem_t *sem, int *sval);

参数:

sem_t *sem:信号量指针

int *sval:信号值指针储存的值

            c.man手册

man sem_getvalue

四.条件变量

        1.理论

设置一个休眠状态,将不访问临界资源的线程休眠,设置一个唤醒条件,当该进程需要访问临界资源时,需要被其他线程唤醒

解决问题:一个生产者对应大量的消费者

        2.pthread_cond_init

                a.功能

初始化条件变量

                b.原型

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;(宏定义实现)

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);

pthread_cond_t *cond:条件变量指针

pthread_condattr_t *cond_attr:条件变量属性(默认为NULL)

                c.例子
pthread_cong_t cond;//定义条件变量
int main(int argc, const char *argv[])
{pthread_cond_init(&cond,NULL);//初始化
}
                d.man手册

man pthread_cond_init

        3.pthread_cond_destroy

                a.功能

销毁条件变量

                b.原型

int pthread_cond_destroy(pthread_cond_t *cond);

参数:

pthread_cond_t *cond:条件变量指针

                c.例子
pthread_cong_t cond;//定义条件变量
int main(int argc, const char *argv[])
{pthread_cond_init(&cond,NULL);pthread_cond_destroy(&cond);//销毁
}
                d.man手册

man pthread_cond_destroy

        4.pthread_cond_wait

                a.功能

将已经被上锁的线程解锁,并让其进入休眠,待被唤醒

                b.原型

int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);

原型:

pthread_cond_t *cond:条件变量指针

pthread_mutex_t *mutex:互斥锁指针

                c.例子
pthread_cong_t cond;//定义条件变量
pthread_mutex_t mutex;//定义互斥锁
void *callback1(void *arg)
{		while(1){pthread_cond_wait(&cond,&mutex);//解锁休眠printf("生产\n");sleep(1);}		pthread_exit(NULL);
}int main(int argc, const char *argv[])
{pthread_cond_init(&cond,NULL);//初始化if(0 != pthread_create(&thread1,NULL,callback1,NULL)){printf("thread1 pthread_create error\n");return -1;}pthread_join(callback1,NULL);pthread_cond_destroy(&cond);//销毁
}
                d.man手册

man pthread_cond_wait

        5.pthread_cond_wait

                a.功能

唤醒休眠队列的第一个线程(休眠队列,按照wait的顺序进入,先进先出)

                b.原型

int pthread_cond_signal(pthread_cond_t *cond);

原型:

pthread_cond_t *cond:条件变量指针

                c.例子
pthread_cong_t cond;//定义条件变量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//定义并初始化互斥锁
void *callback1(void *arg)
{		while(1){sleep(1);printf("生产\n");pthread_cond_signal(&cond);}		pthread_exit(NULL);
}
void *callback2(void *arg)
{	while(1){pthread_mutex_lock(&mutex);//上锁pthread_cond_wait(&cond,&mutex);//解锁休眠printf("%ld:消费\n",pthread_self());pthread_mutex_unlock(&mutex);//解锁}		pthread_exit(NULL);
}int main(int argc, const char *argv[])
{pthread_cond_init(&cond,NULL);//初始化if(0 != pthread_create(&thread1,NULL,callback1,NULL)){printf("thread1 pthread_create error\n");return -1;}pthread_t thread2[5];for(int i = 0; i < 5; i++){if(0 != pthread_create(&thread2[i],NULL,callback2,NULL)){printf("thread2 pthread_create error\n");return -1;}	}pthread_join(thread1,NULL);for(int i = 0; i < 5; i++){pthread_join(thread2[i],NULL);}pthread_cond_destroy(&cond);//销毁条件变量pthread_mutex_destroy(&mutex);//销毁锁return 0;
}

全流程即是:

1.先睡一下具有唤醒条件的线程1

2.线程2上锁,并且解锁进入休眠,并进入休眠队列排队,并阻塞cpu换线程运行

3.如果cpu换到线程1,线程一执行,并唤醒休眠队列第一个,自己阻塞,并运行唤醒的队列

                d.man手册

man pthread_cond_wait

        6.pthread_cond_broadcast

                a.功能

一次性唤醒所有线程

                b.原型

int pthread_cond_broadcast(pthread_cond_t *cond);

参数:

pthread_cond_t *cond:该指针指向的内存中存储条件变量

                c.man手册

man pthread_cond_broadcast

http://www.lryc.cn/news/613567.html

相关文章:

  • latex in overleaf快速通关论文排版
  • FPGA学习笔记——VGA显示静态图片(ROM IP核)
  • 【数据结构入门】双向链表
  • 深入理解 S7-200 SMART 的 “数据语言”:从位到字符串的格式密码
  • C++线程库的学习
  • 【JS】扁平树数据转为树结构
  • 蓝桥杯----数码管、按键、定时器与中断
  • 【感知机】感知机(perceptron)学习算法的收敛性
  • 代码随想录算法训练营 Day20
  • Redis面试精讲 Day 13:Redis Cluster集群设计与原理
  • P1037 [NOIP 2002 普及组] 产生数
  • NFS 服务器
  • Docker容器强制删除及文件系统修复完整指南
  • mysql的InnoDB索引总结
  • 传统防火墙与下一代防火墙
  • 中介效应分析 原理解释 实例分析
  • python中的集合
  • 移动端录屏需求调研:以小熊录屏为例的轻量级实现方案
  • 线程池创建线程
  • jmeter要如何做接口测试?
  • Jmeter使用第一节-认识面板(Mac版)
  • 【线性代数】5特征值和特征向量
  • Vue3获取当前页面相对路径
  • 站在Vue的角度,对比鸿蒙开发中的状态管理
  • Casrel关系抽取
  • vue3 el-select 加载触发
  • AI绘画:生成唐初李世民全身像提示词
  • 【unity实战】使用Unity程序化生成3D随机地牢(附项目源码)
  • 8.3.1 注册服务中心Etcd
  • 【感知机】感知机(perceptron)学习算法的对偶形式