3.16-线程同步

线程同步

  • 同步:即协同步调,按预定的先后次序访问共享数据。
  • 数据同步:指一个线程发出某一功能调用时,没有得到结果前,该调用不返回。同时,其他线程为保证数据一致性,不调用该功能。

数据混乱的原因

  1. 资源共享
  2. 调度随机
  3. 线程之间缺乏必要的同步机制
  • 锁的属性:
    • 系统提供给用户的所有锁全部为”建议锁“,不具备强制性。
    • 如果访问共享数据的线程不拿锁,直接访问共享数据,能访问成功但是数据就会有出现混乱的风险。——拿锁与否完全取决于程序的编写。

互斥量(互斥锁)

pthread_mutex_t mutex;创建互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t  *mu‐
texattr); // 初始化互斥锁int pthread_mutex_lock(pthread_mutex_t *mutex); // 加锁,如果锁被占用,阻塞
int pthread_mutex_trylock(pthread_mutex_t *mutex); // 尝试加锁,不阻塞int pthread_mutex_unlock(pthread_mutex_t *mutex); // 解锁,唤醒阻塞在此锁上的进程int pthread_mutex_destroy(pthread_mutex_t *mutex); // 销毁互斥锁

注意事项:

  1. 锁的粒度越小越好(访问共享数据前,加锁,访问共享数据结束后,立即解锁)。
  2. 互斥锁,本质:结构体。我们可以把它当成整数看待,初始值为 1
  3. 加锁:-- 操作。失败:阻塞线程
  4. 解锁:++ 操作
  5. try:尝试加锁。成功:–,失败,设置错误号。
  • 初始化互斥量:
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; // 静态初始化
pthread_mutex_init(&mut, NULL; // 动态初始化 

死锁

  • 死锁不是锁,是一种错误使用锁的状态。
  • 常见死锁种类:
    1. 对一把锁反复 lock。
    2. 两个线程各自持有一把锁,请求另一把锁。

读写锁

  1. 锁只有一把,可以指定为”读模式“和”写模式“。
  2. 读共享,写独占。
  3. 写锁优先级高。
  • 相较于互斥锁而言,读写锁适合对数据结构读的操作次数远高于写的次数的场景。

操作函数

pthread_rwlock_t rwlock; // 创建读写锁对象int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
  • restrict 关键字:
    • 用来修饰指针标量。被该关键字修饰的指针变量指向的内存操作,只能由本指针完成。

条件变量

  • 条件变量不是锁,通常配合互斥锁使用,也能造成线程阻塞

操作函数

pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // 静态初始化int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); // 动态int pthread_cond_signal(pthread_cond_t *cond); // 唤醒阻塞在条件变量上的线程int pthread_cond_broadcast(pthread_cond_t *cond); // 唤醒阻塞在条件变量上的线程int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); // 等待条件满足
作用:1. 阻塞等待条件满足。2. 解锁已经加锁成功的互斥量。——1. 2. 为一个原子操作,不可再分。...等待...3. 当条件满足,函数返回时,重新加锁
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const
struct timespec *abstime); // 超时退出int pthread_cond_destroy(pthread_cond_t *cond); // 销毁条件变量

信号量

  • 信号量与信号无关
  • 信号量相当于初始值为 N 的互斥量,可以表示同时访问共享数据的线程数。

操作函数

sem_t int sem_init(sem_t *sem, int pshared, unsigned int value);
// 动态初始化,没有静态20:用于线程间同步非 0:用于进程间同步
参 3:信号量的初值 N
返回值:成功:0  失败:-1,errno
int sem_destroy(sem_t *sem);int sem_trywait(sem_t *sem);int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);int sem_post(sem_t *sem);
// 一次调用做一次 ++ 操作。当信号为 N 的时候再次 ++ 会阻塞。
int sem_wait(sem_t *sem);
// 一次调用做一次 -- 操作。当信号为 0 的时候再次 -- 会阻塞。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/34714.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot前后端不分离,前端如何解析后端返回html所携带的参数

有一个SpringBoot实现的前后端不分离项目,当前端跳转某个界面时,比如下面的菜单树按钮,后端在返回页面menuTree.html时,还携带了一个参数角色roleId,以便打开菜单树,还要根据这个角色查询对应的分配授权的菜…

操作系统八股文整理(一)

操作系统八股文整理 一、进程和线程的区别二、进程与线程的切换过程一、进程切换进程切换的步骤: 二、线程切换线程切换的步骤: 三、进程切换与线程切换的对比四、上下文切换的优化 三、系统调用一、系统调用的触发二、从用户空间切换到内核空间三、执行…

卷积神经网络(CNN)之 EfficientNet

在深度学习领域,模型的计算效率与性能之间的平衡一直是一个核心挑战。随着卷积神经网络(CNN)在图像分类、目标检测等任务中取得显著成果,模型的复杂度和计算需求也急剧增加。2019年,Google Research 提出的 EfficientN…

leetcode0031 下一个排列-medium

1 题目: 下一个排列 官方标定难度:中等 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如,arr [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一…

Suno的对手Luno:AI音乐开发「上传参考音频 - 方式二:通过URL的方式」 —— 「Luno Api系列|AI音乐API」第12篇

导读 今天来看下Luno Api的上传参考音频 - 方式一:通过二进制流的方式。 参考文件,主要是用于在创作的过程中,希望AI参考这个音乐的曲风和声音来进行创作, 这一节看看如何直接使用url的方式进行实现。 申请和使用 「已经有API…

【开源+代码解读】Search-R1:基于强化学习的检索增强大语言模型框架3小时即可打造个人AI-search

大语言模型(LLMs)在处理复杂推理和实时信息检索时面临两大挑战:知识局限性(无法获取最新外部知识)和检索灵活性不足(传统方法依赖固定检索流程)。现有方法如检索增强生成(RAG)和工具调用(Tool-Use)存在以下问题: RAG:单轮检索导致上下文不足,无法适应多轮交互场景…

Blender-MCP服务源码2-依赖分析

Blender-MCP服务源码2-依赖分析 有个大佬做了一个Blender-MCP源码,第一次提交代码是【2025年3月7号】今天是【2025年月15日】也就是刚过去一周的时间,所以想从0开始学习这个代码,了解一下大佬们的开发思路 1-核心知识点 from mcp.server.fas…

【孟德尔随机化】Leave-one-out analysis的异常点,判断

下面Leave-one-out analysis的结果,第一条线代表去掉rs174564的结果,一些文献把这种情况判断为异常点/离群点,我们接下来看看其他结果 散点图的结果,最旁边的就是rs174564,这个SNP的点 在看下RadialMR的结果&#xff0…

【计算机网络】2物理层

物理层任务:实现相邻节点之间比特(或)的传输 1.通信基础 1.1.基本概念 1.1.1.信源,信宿,信道,数据,信号 数据通信系统主要划分为信源、信道、信宿三部分。 信源:产生和发送数据的源头。 信宿:接收数据的终点。 信道:信号的传输介质。 数据和信号都有模拟或数字…

kubernetes|云原生|部署单master的kubernetes 1.25.5版本集群完全记录(使用contained 运行时)

一、 部署目标: kubernetes版本1.19,1.23的前后差异还是比较巨大的,到1.25版本,为了追求高性能,自然还是需要使用containerd,本文将主要讲述在centos7虚拟机下部署kubernetes 1.25.5集群,使用…

DeepSeek+Dify本地部署私有化知识库

1.Windows安装docker Windows安装Docker-CSDN博客 2.安装olloma https://ollama.com/ 安装完成,可以在桌面右下角看到olloma图标 3.安装deepseekR1模型 ollama官网(deepseek-r1),找到deepseek模型 选择合适大小的模型&#xff…

[Linux][经验总结]Ubuntu6.11.0 docker更换镜像源(实操可用的正确方法)

一、前言 关于Ubuntu更换docker镜像源,网上有很多的教程,但在实操中发现,更换的源无法生效——原因是我的docker是在系统安装时,选择附加安装的package的方式安装的。 现将处理过程记录如下。 二、获取镜像源 在网上随便找个几…

NHANES指标推荐:BRI!

文章题目:Association of body roundness index with cardiovascular disease in patients with cardiometabolic syndrome: a cross-sectional study based on NHANES 2009-2018 DOI:10.3389/fendo.2025.1524352 中文标题:心脏代谢综合征患者…

3.水中看月

前言 这篇文章讲解套接字分配IP地址和端口号。这部分内容也相对有些枯燥,但并不难,而 且是学习后续那些有趣内容必备的基础知识(计算机网络基础)。 一、分配给套接字的IP地址与端口号 IP是InternetProtocol(网络协议…

Linux驱动开发-①pinctrl 和 gpio 子系统②并发和竞争③内核定时器

Linux驱动开发-①pinctrl 和 gpio 子系统②并发和竞争③内核定时器 一,pinctrl 和 gpio 子系统1.pinctrl子系统2.GPIO子系统 二,并发和竞争1.原子操作2.自旋锁3.信号量4.互斥体 三,按键实验四,内核定时器1.关于定时器的有关概念1.…

奇安信二面

《网安面试指南》https://mp.weixin.qq.com/s/RIVYDmxI9g_TgGrpbdDKtA?token1860256701&langzh_CN 5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39…

Python库安装报错解决思路以及机器学习环境配置详细方案

文章目录 概要第三方库gdalpymoltalibmahotasgraphviznltk-datalazypredictscikit-surprisenb_extensionspyqt5-toolsspacy、en_core_web_sm 机器学习GPU-torch安装torch_geometric安装ubuntu安装显卡驱动dlib安装torch-cluster、torch-scatter、torch-sparse和torch-geometric…

Power Apps 技术分享:连接SharePoint列表数据源

前言 在使用Power Apps的时候,使用列表作为数据源是非常方便和经济的,列表创建简单,SharePoint的存储也不像Dataverse需要按照容量付费。 正文 1.我们先在SharePoint中建一个列表,添加一些测试数据,如下图:…

【Linux】learning notes(4)cat、more、less、head、tail、vi、vim

文章目录 catmore 查看整个文件less 查看整个文件head 查看部分文件tail 查看部分文件vim / vi cat cat 命令在 Linux 和 Unix 系统中非常常用,它用于连接文件并打印到标准输出设备(通常是屏幕)。虽然 cat 的基本用法很简单,但它…

C++11函数包装器

目录 std::function 注意事项 包装静态成员函数 包装非静态成员函数 std::bind 用法 应用场景 std::function function是C11引入的类,可以用任何可调用对象作为参数,构造出一个新对象。 可调用对象有函数指针,仿函数,lamb…