RPC与Thread笔记

embedded/2024/9/25 2:31:23/
  • 线程=“执行线程”

    • 线程允许一个程序同时做很多事
    • 每一个线程就像普通非线程程序一样,都是串行执行
    • 线程之间共享内存
    • 每个线程都包含每个线程的状态,所以它们有
      • 程序计数器,寄存器,堆栈,就绪挂起执行等状态
  • 线程的好处

    • I/O并发
      • 客户端并行的向多个服务器发送请求并且等待响应
      • 服务器端处理多个客户端请求;每个请求都可能阻塞
      • 当等待从磁盘读取客户机X的数据时,处理来自客户端Y的请求
    • 多核性能
      • 在多个核心上并行执行代码
    • 便捷性
      • 在后台,每秒检查一次每个worker是否还活着
  • 除了线程有可替代方案吗

    • 有:在单线程中编写明确交错活动的代码。通常称其为“事件驱动”

    • 保存每个活动的状态表。 eg:每个客户端的请求

    • One "event" loop that:checks for new input for each activity (e.g. arrival of reply from server),does the next step for each activity,updates state.
      
    • 事件驱动可以实现I/O并发,并且消除了线程的成本(可观),但无法获得多核的速度,并且编程很麻烦

  • 编写线程的挑战

    • 安全的共享数据
      • 如果两个线程同时执行n=n+1或者一个线程读取数据,另一个线程递增此数据。这就是所谓的竞争——通常是一个常见的错误,
        • 可以通过使用锁来避免
        • 可以刻意避免共享可变数据
    • 线程之间的协调
      • 一个线程在生成数据,另一个线程在消费数据(消费者如何等待(并释放CPU),生产者如何唤醒消费者)
        • 使用GO中的channels
        • sync.Cond or sync.WaitGroup
    • 死锁
      • 通过锁和通信进行循环(如RPC或者Go channels)
  • 最简单的故障处理方案:“尽最大努力交付”的RPC

    • Call() 等待响应一段时间
    • 如果没有回应重新发送请求
    • 这样做几次
    • 然后放弃并返回错误
  • “尽最大努力交付”对应用程序来说如何?

    • 一种特别糟糕的情况
      • 客户端执行:
        • put(“k”,10);
        • put(“k”,20);
        • 均成功(但网络延迟)
      • 当get(“k”)
        • [diagram, timeout, re-send, original arrives late]
  • 什么时候用“尽最大努力交付”

    • 只读操作
    • 重复执行无任何反作用的操作
      • eg:DB检查记录是否已被插入
  • 更好的RPC行为:“最多执行一次的”RPC

    • 理念:如果没有resp,客户端重新发送请求

      • 服务器端的RPC代码检测重复请求
      • 返回之前的回复,而不需要重新处理
    • 如何检测重复请求

      • 客户端每次请求时包含唯一性索引 ID(XID),再次发送时使用相同的XID

      • 服务器端:

        • server:if seen[xid]:r = old[xid]elser = handler()old[xid] = rseen[xid] = true
          
  • 如何避免庞大的seen[xid]表

    • 想法:
      • 每个客户端有一个唯一性ID(也许是一个大随机数),为每一个RPC分配递增的序列号
      • 客户端在每次RPC中包括“已看到所有回复<=X”
      • 就类似于TCP序列号和ACKs,或者只允许客户端同时有一个未完成的RPC
      • 这样服务器就能保持O(客户端数),而不是O(XID)
  • 服务器最终必须丢弃旧RPC或者旧客户端的信息,何时丢弃是安全的,当原始请求仍在执行时,如何处理重复请求

    • 为每一个正在执行的RPC设置“待处理”标志;等待或者忽略
  • 当线程并行执行的时候,如果内核数量少于可运行的线程数,运行时将抢先在线程之间分配内核

  • 单线程和多线程在程序内存地址空间的区别

  • 在这里插入图片描述

    • 如果两个线程在单核CPU上运行,当从运行一个线程 (T1) 切换到运行另一个线程 (T2) 时,必须进行上下文切换。线程之间的上下文切换与进程之间的上下文切换非常相似,因为在运行T2之前必须保存T1的寄存器状态并恢复T2的寄存器状态。对于进程,我们将状态保存到进程控制块(PCB);现在,我们需要一个或多个线程控制块(TCB)来存储进程的每个线程的状态。与进程相比,我们在线程之间执行的上下文切换有一个主要区别:地址空间保持不变(即不需要切换我们正在使用的页表)。
    • 线程和进程的另一个主要区别是堆栈,每个线程都有一个堆栈。假设我们有一个多线程进程,其中有两个线程;生成的地址空间看起来有所不同(图 26.1,右)。
    • 以前,堆栈和堆可以独立增长,只有当地址空间空间不足时才会出现问题。在这里,我们不再有这么好的情况了。幸运的是,这通常是可以的,因为堆栈通常不必很大。
  • 协程与线程的区别在于协程是完全在应用程序内 (低特权运行级) 实现的,不需要操作系统的支持,占用的资源通常也比操作系统线程更小一些。协程可以随时切换执行流的特性,用于实现状态机、actor model, goroutine 等。


http://www.ppmy.cn/embedded/33301.html

相关文章

Nutch库入门指南:利用Java编写采集程序,快速抓取北京车展重点车型

概述 在2024年北京车展上&#xff0c;电动汽车成为全球关注的焦点之一。这一事件不仅吸引了全球汽车制造商的目光&#xff0c;也突显了中国市场在电动汽车领域的领先地位。117台全球首发车的亮相&#xff0c;其中包括30台跨国公司的全球首发车和41台概念车&#xff0c;彰显了中…

Hive 表定义主键约束

文章目录 1.建表语句2.主键约束3.主键约束的意义参考文献 1.建表语句 先看一下官方给的完整的见表语句&#xff1a; CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- (Note: TEMPORARY available in Hive 0.14.0 and later)[(col_name data…

Java:Map和Set

一、搜索树 在真正学习Map和Set之前&#xff0c;我们有必要先来了解一种树型结构&#xff1a;二叉搜索树&#xff01; 1、概念 二叉搜索树又被称为【二叉排序树】&#xff0c;顾名思义&#xff0c;这是一颗排好序的树&#xff01;它或者是一颗空树&#xff0c;或者是具有以下性…

fatal: fetch-pack: invalid index-pack output

解决方案&#xff1a;git clone --depth1 要克隆的git地址 下载最近一次提交的代码 其他分支的内容都不下载 这样整体下载体量就变小了 执行命令&#xff1a;git clone --depth 1 https://gitlab.scm321.com/ufx/xxxx.git

u-boot引导加载程序的命令列表

2024年5月4日&#xff0c;周六下午 这是u-boot引导加载程序的命令列表&#xff0c;提供了各种功能来配置系统、加载内核和文件系统、进行网络引导等操作。下面是每个命令的简要说明&#xff1a; ?: 显示命令帮助信息的别名。base: 打印或设置地址偏移量。bdinfo: 打印板信息结…

3.SpringSecurity基本原理

SpringSecurity本质是一个过滤器链。十多个过滤器构成一个过滤器链。 这些过滤器在项目启动就会进行加载。每个过滤器执行放行操作才会执行下一个过滤器。 常见过滤器 FilterSecurityInterceptor 是一个方法级的权限过滤器&#xff0c;基本位于过滤器链的最底部。 Excepti…

IoTDB 入门教程 基础篇③——基于Linux系统快速安装启动和上手

文章目录 一、前文二、下载三、解压四、上传五、启动六、执行七、停止八、参考 一、前文 IoTDB入门教程——导读 二、下载 下载二进制可运行程序&#xff1a;https://dlcdn.apache.org/iotdb/1.3.1/apache-iotdb-1.3.1-all-bin.zip 历史版本下载&#xff1a;https://archive.…

【华为OD机试C卷D卷】文件缓存系统(C++/Java/Python)

【华为OD机试】-(A卷+B卷+C卷+D卷)-2024真题合集目录 【华为OD机试】-(C卷+D卷)-2024最新真题目录 题目描述 请设计一个文件缓存系统,该文件缓存系统可以指定缓存的最大值(单位为字节)。 文件缓存系统有两种操作: 存储文件(put)读取文件(get)操作命令为: put fileNam…