• 深入理解函数线程安全与可重入


    1. 函数线程安全

    ① 函数线程安全基本定义

    (1)线程安全:多个线程并发执行同一函数时,不会出现不同的结果,我们就说该函数是线程安全的

    (2)线程不安全:如果多线程并发执行同一函数时会产生不同的结果,则称该函数是线程不安全的

    注:线程不安全的原因大多说是因为对全局变量和静态变量的操作

    ② 常见线程不安全函数

    (1)不保护共享变量的函数

    (2)函数状态随着被调用,状态发生变化的函数

    (3)返回指向静态变量指针的函数

    (4)调用线程不安全函数的函数

    ③ 常见线程安全的情况

    (1)每个线程对全局变量或者静态变量只有读取的权限,而没有写入的权限,一般来说这些线程是安全的;

    (2)类或者接口对于线程来说都是原子操作;

    (3)多个线程之间的切换不会导致该接口的执行结果存在二义性;

    2. 可重入函数 

    ① 基本定义

    (1)可重入函数:一个可重入的函数简单来说就是可以被中断、且重新进入也不会出错的函数。也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误

    (2)不可重入函数:由于使用了一些系统资源,比如全局变量区、中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下

    注:可重入函数也可以这样理解,重入即表示重复进入,首先它意味着这个函数可以被中断,其次意味着它除了使用自己栈上的变量以外不依赖于任何环境(包括static),这样的函数就是purecode(纯代码)可重入,可以允许有多个该函数的副本在运行,由于它们使用的是分离的栈,所以不会互相干扰

    ② 可重入函数需要满足的条件

    (1)不使用全局变量或静态变量;

    (2)不使用malloc或者new开辟出的空间;

    (3)不调用不可重入函数

    (4)不返回静态或全局数据,所有数据都有函数的调用者提供

    (5)使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据

    ③ 不可重入函数符合以下条件之一

    (1)调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的。

    (2)调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构

    (3)函数体内使用了静态的数据结构

    ④ 可重入函数分类

    (1)显式可重入函数:如果所有函数的参数都是传值传递的(没有指针),并且所有的数据引用都是本地的自动栈变量(也就是说没有引用静态或全局变量),那么函数就是显示可重入的,也就是说不管如何调用,我们都可断言它是可重入的。

    (2)隐式可重入函数:可重入函数中的一些参数是引用传递(使用了指针),也就是说,在调用线程小心地传递指向非共享数据的指针时,它才是可重入的。

    注:可重入函数可以有多余一个任务并发使用,而不必担心数据错误,相反,不可重入函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据,可重入函数要么使用本地变量,要么在使用全局变量时保护自己 的数据。

  • 相关阅读:
    004 RequestMappingHandlerMapping
    003 HandlerMapping
    002 环境配置
    001 springmvc概述
    011 使用AOP操作注解
    010 连接点信息
    009 通知类型
    一台服务器的IIS绑定多个域名
    程序包需要 NuGet 客户端版本“2.12”或更高版本,但当前的 NuGet 版本为“2.8.50313.46”
    通过ping 主机名,或者主机名对应的IP地址
  • 原文地址:https://www.cnblogs.com/wulei0630/p/9506164.html
Copyright © 2020-2023  润新知