【南京大学操作系统(蒋岩炎)】(三)理解并发程序执行 | 并发控制 : 互斥


前言

我目前正在学jyy的操作系统,该文章为我的笔记。
学习链接 : 链接点击跳转

在这里插入图片描述

互斥算法

  • 只用内存的读写 写一个 lock() unlock()
  • 山寨的lock 失败的原因 : 不能保证原子的一致性

Peterson 算法

  • 实现的是一个内存共享模型

  • 想象成一个真实的物理空间
    在这里插入图片描述

  • 在这里插入图片描述
    在这里插入图片描述

  • 这也证明了为什么 要贴上对方的名字 +在这里插入图片描述

在这里插入图片描述

  • take-away
  • 状态机
    在这里插入图片描述
  • 尽可能的去实现model checker 判断程序的正确性

并发控制 :互斥(自选锁、互斥锁、futex)

  • Q:如何在多处理器上实现互斥???
    回顾
    并发编程
    理解并发的工具
    线程 = 人 (大脑能完成局部存储和计算)
    共享内存 = 物理世界 (物理世界天生并行)
    一切都是状态机

互斥 (mutual exclusion),“互相排斥”

实现 lock_t 数据结构和 lock/unlock API:

typedef struct {
    
    
  ...
} lock_t;
void lock(lock_t *lk);
void unlock(lock_t *lk);
//一把 “排他性” 的锁——对于锁对象 lk
//如果某个线程持有锁,则其他线程的 lock 不能返回

问题的思考

  • 由于软件无法解决的lock ,因为软件的主要部分是计算
  • 实现lock还需要系统有一个裁决机制
    在这里插入图片描述
  • 如果把 内敛汇编的 lock 去掉的话 , 则会出错

自旋锁的实现

x86 原子操作:LOCK 指令前缀

  • 例子:[sum-atomic.c](http://jyywiki.cn/pages/OS/2022/demos/sum-atom
  • Atomic exchange (load + store)
  • C++的 stdayomic.h
    在这里插入图片描述
    在这里插入图片描述

用 xchg 实现互斥 (自旋锁)

  • 例子 : 每次去厕所门口都需要exchange 只有在在上厕所的人身上才有钥匙
    在这里插入图片描述

  • 所有的lock的指令 都可以保证 lock指令的书写顺序 (多线程上)

  • 下一条 指令执行之前 可以看到它上一条指令所有的事情

  • 所有的指令都不能越过原子指令(上一lock指令前执行的全部指令)
    在这里插入图片描述

旧的x86原子操作

  • 当俩个cpu处理共享一个内存
  • 上锁 加上lock汇编指令前缀
  • 但是存在负担 1byte 代价大

MESI(缓存一致性)

  • 但现在有 共享缓存锁 : 保证缓存的一致性
  • MESI
    在这里插入图片描述

RISC

在这里插入图片描述

Compare-and-Swap 的 LR/SC 实现

在这里插入图片描述

互斥锁的实现

自旋锁的缺陷

  • 如果一个进程拿了一把钥匙,其他的进程都要等待,如果进程多的话,那浪费可想而知
  • 达到了 多线程比单线程还慢

在这里插入图片描述
在这里插入图片描述

Scalability

在这里插入图片描述

使用场景

在这里插入图片描述

互斥锁 (Mutex Lock)

  • C语言只负责计算的部分 , 剩下的全部交给操作系统
    在这里插入图片描述
    sum-scalability.c

在这里插入图片描述

Futex = Spin + Mutex

Spin VS Mutex

在这里插入图片描述

Futex: Fast Userspace muTexes

在这里插入图片描述

在这里插入图片描述

  • gdb 调试 set scheduler-locking on, info threads, thread X (待完成 ,暂时功底不够)
  • vim 替换操作
    在这里插入图片描述

总结

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_49486457/article/details/127721541