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

Linux16(1) 线程同步

目录

1、概念

2、线程的实现:

3、线程同步:

4、使用信号量:

5、使用信号量实现进程同步:

6、使用互斥锁

7、使用互斥锁实现线程同步

8、读写锁

9、使用读写锁

10、使用读写锁实现进程同步


1、概念

线程:进程内部的一条执行路径

进程:正在运行的程序

并发:在一段时间内两者交替运行

并行,在一段时间内,两者同时执行,必须有两个处理器

2、线程的实现:

用户级线程:模拟出来多条路径,在内核眼里依旧是一条路径,他的出现不需要操作系统参与,可以创建特别多的线程,开销小但是无法使用多个处理器(只能并发)

(linux)内核级线程:通过内核提供的接口去创建线程,创建开销大,但是可以实现并行(使用多个处理器)

组合:可以利用多处理器的资源,在用户空间可以创建更多线程,对于后期线程的创建来说,开销小

在Linux系统上,没有线程的概念,每一个线程都是当作进程来实现的,是一个和其他进程共享某些资源的进程,都拥有属于自己的内存控制块

3、线程同步:

信号量     互斥锁     条件变量      读写锁

对程序的执行进行控制,保证程序的正确性,多个线程按照一定顺序执行。

没有进行同步线程的程序
int g_count=1;
void* fun(void *arv)
{
for(int i=0;i<1000;i++)
{
printf("g_count=%d",g_count++);
}
}
int main()
{
pthread_t id[5];
for(int i=0;i<5;i++)
{
pthread_creat(&id[i],NULL,fun,NULL);
}
for(int i=0;i<5;i++)
{
pthread_join(id[i],NULL);//等待其他线程结束
}
exit(0);
}
对于最终结果,因为在运行过程中可能出现在同一时间,两个线程对同一个数据进行操作的情况,所以结果可能为5000,也可能小于5000

4、使用信号量:

头文件#include<semphore.h>

初始化信号量:sem_t sem;

执行p操作:sem_wait(&sem);

执行v操作:sem_post(&sem);

销毁:sem_destroy(&sem);

5、使用信号量实现进程同步:

使用了信号量进行线程同步
#include<semaphore.h>
int g_count=1;
sem_t sem;
void* fun(void *arv)
{
for(int i=0;i<1000;i++)
{
sem_wait(&sem);//p操作
printf("g_count=%d",g_count++);
sem_post(&sem);//v操作
}
}
int main()
{
sem_init(&sem,0,1);//sem=1
//信号量初始化pthread_t id[5];
for(int i=0;i<5;i++)
{
pthread_creat(&id[i],NULL,fun,NULL);
}
for(int i=0;i<5;i++)
{
pthread_join(id[i],NULL);//等待其他线程结束
}
sem_destroy(&sem);//销毁信号量
exit(0);
}
//结果无论怎么执行都是5000

6、使用互斥锁

要不我用要不你有,在使用之前先加锁,使用时候再解锁,其他人用再加锁再解锁

定义:pthread_mutex_t mutex;

初始化:pthread_mutex_init(&mutex,NULL);

加锁:pthread_mutex_lock(&mutex);

解锁:pthread_mutex_unlock(&mutex);

销毁:pthread_mutex_destroy(&mutex);

7、使用互斥锁实现线程同步

使用互斥锁实现线程同步
int g_count=1;pthread_mutex_t mutex;
//定义互斥锁
void* fun(void *arv)
{
for(int i=0;i<1000;i++)
{
pthread_mutex_lock(&mutex);
//加锁
printf("g_count=%d",g_count++);
pthread_mutex_unlock(&mutex);
//解锁
}
}
int main()
{
pthread_mutex_init(&mutex,NULL);
//互斥锁初始化
pthread_t id[5];
for(int i=0;i<5;i++)
{
pthread_creat(&id[i],NULL,fun,NULL);
}
for(int i=0;i<5;i++)
{
pthread_join(id[i],NULL);//等待其他线程结束
}
exit(0);
pthread_mutex_destroy(&mutex);
}

8、读写锁

读写锁允许多个线程同时读取一个资源,但只允许一个线程对他进行修改

读写锁有两种状态:读模式和写模式。多个线程可以同时持有读模式的锁,以允许并发读取共享资源。

当有线程持有读模式锁时,其他线程也可以继续获取读模式锁,但不能获取写模式锁。只有当没有线程持有读模式锁时,才能获取写模式锁进行写操作。

9、使用读写锁

定义:pthread_rwlock_t lock;

初始化:pthread_rwlock_init(&lock,NULL);

写加锁:pthread_rwlock_wrlock(&lock);

写解锁:pthread_rwlock_unlock(&lock);

读加锁:pthread_rwlock_rdlock(&lock)

读解锁:pthread_rwlock_unlock(&lock)

销毁锁:pthread_rwlock_destroy(&lock)

10、使用读写锁实现进程同步

pthread_rwlock_t lock;void *pthread_fun(void*arg)
{
for(int i=0;i<10;i++)
{
pthread_rwlock_wrlock(&lock);
printf("w star");
sleep(1);
printf("w end");
pthread_rwlock_wrlock(&lock);
sleep(1);
}
}void*pthread_fun1(void*arg)
{
for(int i=0li<10;i++)
{
pthread_rwlock_rdlock(&lock);
printf("r1 star");
sleep(1);
printf("r1 end");
pthread_rwlock_rdlock(&lock);
}
}void*pthread_fun2(void*arg)
{
for(int i=0;i<5;i++)
{
pthread_rwlock_rdlock(&lock);
printf("r2 star");
sleep(1);
printf("r2 end");
pthread_rwlock_unlock(&lock);
sleep(1);
}
}int main()
{
pthread_rwlock_init(&lock,NULL);
pthread_t id1,id2,id3;
pthread_create(&id1,NULL,pthread_fun1,NULL);
pthread_create(&id2,NULL,pthread_fun2,NULL);
pthread_create(&id3,NULL,pthread_fun,NULL);pthread_join(id1,NULL);
pthread_join(id2,NULL);
pthread_join(id3,NULL);pthread_rwlock_destroy(&lock);
exit(0);
}

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

相关文章:

  • 深入探讨lowess算法:纯C++实现与局部加权多项式回归的数据平滑技术
  • Sui安全篇|详解零知识证明 (ZKP) Groth16的可塑性
  • 记录--webpack和vite原理
  • Windows系统中使用bat脚本启动git bash 并运行指定命令 - 懒人一键git更新
  • elementui form组件出现英文提示
  • 使用windows Api简单验证ISO9660文件格式,以及装载和卸载镜像文件
  • iPhone 15受益:骁龙8 Gen 3可能缺席部分安卓旗舰机
  • 理解持续测试,才算理解DevOps
  • 使用OpenCV与深度学习从视频和图像中精准识别人脸: Python实践指南
  • 面试之快速学习C++11-完美转发,nullptr, shared_ptr,unique_ptr,weak_ptr,shared_from_this
  • android resoure资源图片颜色值错乱
  • leetcode第 357/358 场周赛
  • Jmeter 分布式性能测试避坑指南
  • 基于SpringCloud的会议室预约系统Java基于微服务的会议室报修系统【源码+lw】
  • idea设置忽略大小写
  • re学习(35)攻防世界-no-strings-attached(动调)
  • STM32 F103C8T6学习笔记8:0.96寸单色OLED显示屏显示字符
  • vscode的配置和使用
  • SpringBoot统⼀功能处理
  • LeetCode 每日一题 2023/8/14-2023/8/20
  • 进入微服务阶段后的学习方法
  • C/C++中const关键字详解
  • 【2023新教程】树莓派4B开机启动-树莓派第一次启动-树莓派不使用显示器启动-树莓派从购买到启动一步一步完全版!
  • LA@2@1@线性方程组和简单矩阵方程有解判定定理
  • 如何使用ChatGPT创作一个小说式的虚构的世界
  • 用于量子通信和互联网的光量子芯片
  • 11. Vuepress2.x 关闭夜间模式
  • netty实现websocket通信
  • 两个list如何根据一个list中的属性去过滤掉另一个list中不包含这部分的属性,用流实现
  • Blender 混合现实3D模型制作指南【XR】