线程安全与可重入函数

    在以前的博文中有说过线程,线程是一个执行流,一个指令序列,一个指令分支,为了共享资源而产生的线程,但只要是资源,都会出现资源的数目与操做安全问题,因此在线程这一块,设计了信号量,条件变量,各类锁,来保证资源的访问独占性与原子性。安全

    什么是线程安全?
数据结构

      线程安全指的是在多线程访问状况下,保证线程对临界资源的操做原子性,在临界区中,不容许其余的线程进行插入访问形成了数据的乱序占用而修改,产生逻辑结果不一致的问题。
多线程

      线程不安全就是不提供数据访问保护,出现多个线程前后更改数据形成脏数据。ide

    其实对于线程安全简单来讲,就是保证在多线程状况下,咱们进行的操做,不管是否控制临界区的插入访问,只要保证数据逻辑结果的原子性就是线程安全的,但若出现数据的乱序操做或者中断操做,达不到预期的结果则就是线程不安全的。
函数


    那么对于线程安全来讲,咱们经过各类控制临界区的执行权限来进行限制,能够阅读以前的博文来进行线程的同步与互斥,线程自己就是为了共享资源而产生,利用同步与互斥来进行任务逻辑上的运行,既保证协同,有保证逻辑独有。spa

    

    线程就是一个执行流,一个指令序列,一个指令分支,也就是一个函数。那么对于函数而言,存在着不须要进行互斥控制的状况,也就是在多线程状况下,不管线程之间是如何运行插入修改,都可以保证数据的正确性,就是可重入函数。信号捕捉也是进行函数的操做,因此信号跟线程在原理上是类似的。线程

   

先举一个不可重入函数的例子:设计

 wKiom1cvIIyR3Fj9AACYMWS253c132.png

针对这张图片,咱们来分析一下他的过程。blog

  1. 在insert函数中,咱们很明显的知道,他是一个头插的函数,
    图片

  2. 而后在insert函数执行之中,假若在p->next = head以后,head = p以前产生了一个信号捕捉,或者同时运行多个线程,在多个线程之中,线程中断插入在这之间,就会出现图片上的结果。

  3. 也就是咱们要达到的目的是咱们要插入2个数据,可是却只插入了一个数据,另一个数据出现了空间浪费,目的不达到,并产生了脏数据。

    insert函数被不一样的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入,insert函数访问一个全局链表,有可能由于重入而形成错乱,像这样的函数称为不可重入函数,反之,若是一个函数只访问本身的局部变量或参数,则称为可重入(Reentrant) 函数。

    

为何两个不一样的控制流程调用同一个函数,访问它的同一个局部变量或参数就不会形成错乱?

    在线程之中,线程虽然强调资源共享,可是他们的栈倒是独有的,因此访问它的同一个局部变量或参数就不会形成错乱。


不可重入函数的条件:

调用了malloc或free,由于malloc也是用全局链表来管理堆的。

调用了标准I/O库函数。标准I/O库的不少实现都以不可重入的方式使用全局数据结构。

SUS规定有些系统函数必须以线程安全的方式实现,这里就不列了。



总结:

    对于线程安全来讲,就是保证在多线程逻辑环境下的数据操做不产生反作用影响,从而出现了各类保证线程安全的操做,条件变量,信号量,各类锁。

    线程其实是一个指令序列,一个执行流,一个函数。因此对于线程之中,若在多线程环境下不论怎么中断插入,都不影响数据逻辑的函数叫作可重入函数。

相关文章
相关标签/搜索