操作系统学习笔记 原来自旋锁还可以这样实现!

baskbull
• 阅读 2464

在java中我们知道对线程使用CAS(compare and swap)来实现自旋锁,在没有学习操作系统之前,我以为这是唯一一种方法了。但是今天学到了操作系统中的同步互斥,终于明白了原来CAS、TS、Swap这些都是硬件提供的原子操作罢了!不仅CAS可以实现自旋锁,TS(Test and Set)同样可以!

临界区

  • 临界区

进程中访问临界资源的一段需要互斥执行的代码

  • 进入区

    • 检查可否进入临界区的一段代码
    • 如可进入,设置相应“正在访问临界区”标志
  • 退出区

    • 清楚“正在访问临界区”标志
  • 剩余区

    • 代码的剩余部分

临界区的访问规则

  • 空闲则入
    • 没有进程在临界区时,任何进程可进入
  • 忙则等待
    • 有进程在临界区时,其他进程均不能进入临界区
  • 有限等待
    • 等待进入临界区的进程不能无限期等待
  • 让权等待(可选)
    • 不能进入临界区的进程,应释放CPU(如转换到阻塞状态)

临界区的实现方法

  • 禁用中断
  • 软件方法
  • 更高级的抽象方法

方法3:高级抽象的同步方法

  • 硬件提供了一些同步原语
    • 中断禁用,原子操作指令
  • 操作系统提供更高级的变成抽象来简化进程同步
    • 例如:锁、信号量
    • 用硬件原语来构建

锁lock

  • 锁是一个抽象的数据结构
    • 一个二进制变量(锁定/解锁)
    • Lock::Acquire()
      • 锁被释放前一直等待,然后得到锁
    • Lock::Release()
      • 释放锁,唤醒任何等待的进程

原子操作指令

  • 现代CPU体系结构都提供了一些特殊的原子操作指令

  • 测试和置位(Test-and-set)指令

    • 从内存单元中读取值
    • 测试该值是否为1(然后返回真或假)
    • 内存单元值设置为1

使用TS指令实现自旋锁

class Lock{
    int value = 0;
}
Lock::Acquire() {
    while( test-and-set(value))
        ; //spin
}
Lock::Release() {
    value = 0;
}

如果锁被释放,那么TS指令读取0并将值设置为1

  • 锁被设置为忙并且需要等待完成

如果锁处于忙状态,那么TS指令读取1并将值设置为1

  • 不改变锁的状态并且需要循环

它的问题是线程在等待的时候也要消耗CPU的时间

操作系统学习笔记 原来自旋锁还可以这样实现!

很多原子操作指令都可以做到同步互斥中用户态难以做到的事情。

Hello World社区的界面很美观~希望可以和Hello World一起成长

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
java 里面 的锁
A、乐观锁、悲观锁B、偏向锁、轻量级锁、重量级锁C、互斥锁、自旋锁、适应性自旋D、可重入锁、读写锁E、公平锁、非公平锁F、总线锁、缓存锁(linux操作系统底层,由CPU提供的锁)G、锁优化:减少锁持有时间、减小锁粒度、锁分离、锁粗化、锁消除信号量与互斥量:信号
Wesley13 Wesley13
3年前
java面试题汇总,不断更新中。。。
JVM,并发,锁相关:1.请你谈谈对volatile的理解,volatile是否存在伪共享问题。2.cas你知道吗?3.原子类AtomicInteger的ABA问题谈谈?原子更新引用知道吗?4.公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁。5.CountDownLatch、CyclicBarrier、S
Wesley13 Wesley13
3年前
Java并发编程:AQS对CLH锁的优化
自旋锁适用于锁占用时间短,即锁保护临界区很小的情景<AQS的自旋锁详解(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzU3OTc1MDM1Mg%3D%3D%26mid%3D2247495307%26idx%3D1%26sn
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
JDK里的自旋锁
自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时才能进入临界区。JDK里面自旋锁的实现有SynchronousQueue 和LinkedTransferQueue。 本文只是自己对源码的简单理解。先说公平锁,先等待的线程先获得数据。SynchronousQueue的内部类TransferQueue实现了公平锁。
Stella981 Stella981
3年前
JVM中锁优化简介
本文将简单介绍HotSpot虚拟机中用到的锁优化技术。自旋锁互斥同步对性能最大的影响是阻塞的实现,挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给系统的并发性能带来了很大的压力。而在很多应用上,共享数据的锁定状态只会持续很短的一段时间。若实体机上有多个处理器,能让两个以上的线程同时并行执行,我们就可以让后面请求锁的那个线程原地自旋(
baskbull
baskbull
Lv1
热爱,是梦想的起点
文章
2
粉丝
0
获赞
1