首页 > 其他分享 >并发原理—如何保证多条指令的原子性(二)

并发原理—如何保证多条指令的原子性(二)

时间:2022-09-26 08:22:07浏览次数:81  
标签:队列 多条 原子 并发 指令 线程 设置 CPU

一、提出问题:一条CPU原语指令如何保证多条指令的原子性

上篇文章我们知道当多个CPU访问(此处访问的含义不仅有读取内存数据的意思,同时也有往内存写入数据的意思)同一个数据时,CPU存在着穿插执行的行为,从而造成数据紊乱的情况,为此CPU提供了锁机制来保证数据一致性,锁机制背后的原理就是通过CPU的一条原子性指令(原语)限制只能有一个CPU执行该指令。但我们的应用程序的某个方法往往是由多条指令(通过汇编器产生的ISA指令集)组成的,那一条原语指令如何保证多条指令的原子性呢?换个问法就是:应用程序的多个线程访问同一个方法时是如何保证线程安全的呢?

二、只有设置标志位成功的线程才可以执行方法

如图所示,应用程序有一个方法,该方法内部存在对数据的写操作,现在有n个线程想同时执行该方法,那么势必会存在多线程并发的问题。那么CPU底层是如何通过一条CPU原语指令保证多条指令的原子性呢?答案就是通过引入一个标志位,让CPU去争抢设置标志位。这些CPU通过原子性指令(lock;add或者lock;sub)来设置标志位,由于是原子操作,那么只有一个CPU能设置成功,也即只有设置标志位成功的线程可以执行方法代码,设置失败的其他线程则要排队进入阻塞队列。

三、设置标志位失败的线程自旋进入阻塞队列

因为设置标志位失败的线程有多个,它们进入队列的过程是要拿到队尾指针,然后把队尾指针指向自己。那么抢这个队尾指针的操作,又是一个原子性操作,通过CPU的原子性指令(lock;cmpxchg)来让多个线程排队进入队列,这个操作称之为自旋。

四、唤醒和排队也是原子性操作

当线程执行完代码后,需要唤醒阻塞队列中的线程继续执行方法,而在唤醒的同时有可能有其他线程在排队进入队列中,所以唤醒和排队这两个操作也是原子性操作。

五、总结

我们绘制完整执行流程图,可以清晰看到CPU是如何通过一条CPU原语保证多条指令的原子性。我们可以通过以下伪代码简要概述上述逻辑过程:

if(设置标志位){   
  // 设置标志位成功的线程执行方法
} else { 
   // 设置失败的线程排队
    for(;;){     
    // 通过CAS进入队列  
    }
}

标签:队列,多条,原子,并发,指令,线程,设置,CPU
From: https://www.cnblogs.com/chuandao/p/16729634.html

相关文章

  • MyBatis——案例——查询-多条件查询-动态条件查询(关键字 if where)
    动态条件查询  SQL语句会随着用户的输入或外部条件的变化而变化,我们称为动态SQL   MyBatis对动态SQL有很强大的支撑:  if  choose(when,otherwise)  tri......
  • 【Linux】指令学习
    Linux学习记录......
  • MyBatis——案例——查询-多条件查询(多参数接收的三种方法)
    查询-多条件查询  编写接口方法:Mapper接口      参数:所有条件查询List<Brand>selectByCondition(intstatus,StringcompanyName,StringbrandName);   ......
  • Spring Cloud与Docker高并发微服务架构设计实施 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1UEa0pb5JSp2lIIcFwzapEw点击这里获取提取码 ......
  • 认识线程,初始并发
    线程学习1. 什么是线程程序是为完成特定任务,用某种语言编写的一组指令的集合,即指一段静态的代码,静态对象进程是程序的一次执行过程,或是正在运行的一个程序。是一......
  • vue3 基础-自定义指令 directive
    上篇内容是关于mixin混入的一些操作,也是关于代码复用层面的,本篇讲自定义指令directive也是为了实现复用而设计的一些小功能啦.先来看看,如果不用directive的场......
  • 关于 find 指令的 +n、-n、n
    描述find指令查找文件时可以通过时间来锁定或缩小搜查范围。其中需要利用到文件的三个时间?:AccessTime(atime)、ModifyTime(mtime)和ChangeTime(ctime)。通常会指定在at......
  • 并发学习记录13:不可变
    问题的提出日期转换的问题在多线程的环境下做日期转换很可能出现线程安全问题:代码:@Slf4j(topic="ch.UnchangeTest01")publicclassUnchangeTest01{publicst......
  • day2-doc指令的练习
    常用的dos指令 #盘符切换 #查看当前目录下的文件dir #切换目录cdchangedirectory  cd/d跨盘切换  cd..切换上级目录 #cls清理屏幕clearscreen ......
  • 编程规约-并发处理-锁
    编程规约-并发处理-锁锁考量锁的性能损耗高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。......