并发控制互斥笔记

整理总结自蒋炎岩老师的b站课程,https://jyywiki.cn/OS/2022/index.html

  • 多处理器系统中数据的一致性和互斥访问

    • 所有的CPU的一级缓存都是连着的,如果是多个CPU的话,用在内存中放置标志位,来保证对当前内容的原子性读取,Xchg指令。
      在这里插入图片描述

    • Lock 指令的现代实现(自旋锁)(类似于悲观锁)

      • int table = YES;void lock() {
        retry:int got = xchg(&table, NOPE);if (got == NOPE)goto retry;assert(got == YES);
        }void unlock() {xchg(&table, YES)
        }
        
      • 通常描述

      • int locked = 0;
        void lock() { while (xchg(&locked, 1)) ; }
        void unlock() { xchg(&locked, 0); }
        
      • 在 L1 cache 层保持一致性 (ring/mesh bus)

        • 相当于每个 cache line 有分别的锁(实际上,这不是传统意义上的锁。在硬件层面,通过缓存一致性协议和高速互连网络,处理器能够确保当一个核心在其L1缓存中修改了某个缓存行时,其他核心能够即时地了解到这一变化。这种机制确保了数据的一致性,而无需显式的锁。)
        • store(x) 进入 L1 缓存即保证对其他处理器可见
          • 但要小心 store buffer 和乱序执行
      • Icache line 根据状态进行协调

        • M (Modified), 脏值
        • E (Exclusive), 独占访问
        • S (Shared), 只读共享
        • I (Invalid), 不拥有 cache line
    • Load-Reserved/Store-Conditional(LR/SC)(类似于乐观锁)

      • LR: 在内存上标记 reserved (盯上你了),中断、其他处理器写入都会导致标记消除

        lr.w rd, (rs1)rd = M[rs1]reserve M[rs1]
        
      • SC: 如果 “盯上” 未被解除,则写入

        sc.w rd, rs2, (rs1)if still reserved:M[rs1] = rs2rd = 0else:rd = nonzero
        
    • 自旋锁的缺陷

      • 性能问题 (0)

        • 自旋 (共享变量) 会触发处理器间的缓存同步,延迟增加
      • 性能问题 (1)

        • 除了进入临界区的线程,其他处理器上的线程都在空转
        • 争抢锁的处理器越多,利用率越低
      • 性能问题 (2)

        • 获得自旋锁的线程

          可能被操作系统切换出去

          • 操作系统不 “感知” 线程在做什么
          • (但为什么不能呢?)
        • 实现 100% 的资源浪费

    • 自旋锁的使用场景

      • 临界区几乎不 “拥堵”
      • 持有自旋锁时禁止执行流切换

      使用场景:操作系统内核的并发数据结构 (短临界区)

      • 操作系统可以关闭中断和抢占
        • 保证锁的持有者在很短的时间内可以释放锁
    • 线程+长临界区的互斥可以解决

      • 把锁的实现放到操作系统里就好啦!

        • syscall(SYSCALL_lock, &lk);
          
          • 试图获得 lk,但如果失败,就切换到其他线程
        • syscall(SYSCALL_unlock, &lk);
          
          • 释放 lk,如果有等待锁的线程就唤醒
        • 其他的线程仍然能继续执行

  • 关于互斥的一些分析

    • 自旋锁 (线程直接共享 locked)
      • 更快的 fast path
        • xchg 成功 → 立即进入临界区,开销很小
      • 更慢的 slow path
        • xchg 失败 → 浪费 CPU 自旋等待
    • 睡眠锁 (通过系统调用访问 locked)
      • 当没有获取到锁将线程转为就绪状态(会频繁切换上下文)
      • 更快的 slow path
        • 上锁失败线程不再占用 CPU
      • 更慢的 fast path
        • 即便上锁成功也需要进出内核 (syscall)
  • 互斥锁

    • 睡眠锁+自旋锁=互斥锁

    • 先在用户空间自旋

      • 如果获得锁,直接进入

      • 未能获得锁,系统调用

      • 解锁以后也需要系统调用

        class Futex:locked, waits = '', ''def tryacquire(self):if not self.locked:# Test-and-set (cmpxchg)# Same effect, but more efficient than xchgself.locked = '🔒'return ''else:return '🔒'def release(self):if self.waits:self.waits = self.waits[1:]else:self.locked = ''@threaddef t1(self):while True:if self.tryacquire() == '🔒':     # Userself.waits = self.waits + '1' # Kernelwhile '1' in self.waits:      # Kernelpasscs = True                         # Userdel cs                            # Userself.release()                    # Kernel@threaddef t2(self):while True:if self.tryacquire() == '🔒':self.waits = self.waits + '2'while '2' in self.waits:passcs = Truedel csself.release()

        Python模拟操作系统实现

        • 更好的设计可以在 fast-path 不进行系统调用

下篇聊并发控制同步

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

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

相关文章

k8s 理论知识基本介绍

目录 一 k8s 理论前言 (一)微服务是什么 1,应用场景 2,API 是什么 (二),微服务 如何做版本迭代 1. Docker镜像构建 2. 版本标记 3. Docker Registry 4. 环境一致性 5. 滚动更新…

mysql NDBcluster数据库集群介绍、部署及配置

前言: MySQL集群是一个无共享的、分布式节点架构的存储方案,旨在提供容错性和高性能。它由三个主要节点组成:管理节点(MGM)、数据节点和SQL节点。 管理节点(MGM) 定义与用途:管理节点是MySQL Cluster的控制中心,负责管理集群内的其他节点。它提供配置数据,启动和停止…

多址通信方式的抗噪声性能和系统容量对比

🏆本文收录于「Bug调优」专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&…

Qt复习第二天

1、菜单栏工具栏状态栏 #include "mainwindow.h" #include "ui_mainwindow.h" #pragma execution_character_set("utf-8"); MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);//菜…

0510_IO5

练习题&#xff1a; #include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <unistd.h>#include <sys/stat.h>#include <fcntl.h>#include <pthread.h>#include <semaphore.h>#incl…

第十一讲:指针(3)

第十一讲&#xff1a;指针&#xff08;3&#xff09; 1.字符指针变量1.1存储一个字符1.2存储一个字符串1.3一个有趣的面试题 2.数组指针变量2.1什么是数组指针变量2.2数组指针变量的初始化 3.二维数组传参的本质4.函数指针变量4.1介绍函数指针变量4.2 两段有趣的代码4.2.1代码1…

TP5000是一款开关降压型单节锰锂电池/磷酸铁锂电池充电管理芯片IC

一般概述 TP5000是一款开关降压型单节锰锂电池/磷酸铁锂电池充电管理芯片。其QFN16超小型封装与简单的外围电路&#xff0c;使得TP5000非常适用于便携式设备的大电流充电管理应用。同时&#xff0c;TP5000内置输入过流、欠压保护、芯片过温保护、短路保护、电池温度监控…

videosapi、强大的微信管理api

接口地址&#xff1a;videosapi.com 同步个人收藏夹 {"appId": "{{appid}}","syncKey": "" } 出参 {"ret": 200,"msg": "操作成功","data": {"syncKey": "CAESCAgBEJyi9e4…

设计模式1——初步认识篇

设计模式1——初步认识篇 一、先让我们浅聊一下面向对象和设计模式。 说起设计模式&#xff0c;我第一次听到它&#xff0c;是在学习面向对象的时候。那么什么是面向对象&#xff0c;什么是设计模式&#xff0c;而且设计模式和面向对象又有什么关系呢&#xff1f; 1、什么是面…

G.AB路线【蓝桥杯】/bfs+可重复走

AB路线 bfs可重复走 思路&#xff1a;本题和传统的bfs题目不同&#xff0c;本题为了满足题目先走K个A再走K个B&#xff0c;可能需要重复走某个格子才能继续走下去&#xff0c;故vis数组可以多开一维&#xff0c;vis[x][y][z]表示第z次走到x行y列这种情况是否出现过 A A A B B …

通用型产品发布解决方案(后端环境搭建)

文章目录 后端renren脚手架配置1.解压后放到项目目录下2.新建商品模块1.创建一个新模块 sunliving-commodity2.删除两个不必要的文件3.pom.xml 引入依赖 3.maven进行聚合管理1.将刚才配置的pom.xml文件复制到父项目下并进行修改2.手动将这个pom.xml加入项目&#xff08;如果右下…

vs2019 里 C++ 20规范的 string 类的源码注释

&#xff08;1&#xff09;读源码&#xff0c;可以让我们更好的使用这个类&#xff0c;掌握这个类&#xff0c;知道咱们使用了库代码以后&#xff0c;程序大致具体是怎么执行的。而不用担心程序出不知名的意外的问题。也便于随后的代码调试。 string 类实际是 库中 basic_strin…