线程安全与可重入总结

    xiaoxiao2025-09-01  128

    总结: ①可重入函数一定是线程安全的; ②可以通过加锁将不可重入函数变成线程安全的; ③线程安全的函数不一定是可重入的; 解释: 根据正常情况,当一个信号发生时,如果进程并没有对该信号进行屏蔽,信号 可能在任意时候打断一个进程的任意一个线程而执行。 一个函数可以是可重入的,也可以是线程安全的,也可以两者都是,或者两者都不是。 1、可重入函数:相对于信号而言,如果该函数A1正在执行过程中,进程接收到一个信号B,在信号处理函数中C,刚好又运行了这个函数A2,当信号处理函数运行返回时(假设在该函数中没有eixt指令),该函数A1还可以接着运行,并且得到正确的结果(这也说明可重入函数不可能依赖于外部的全局变量或者静态变量,因为如果信号处理函数在运行该函数时改变了那些变量的值,则结果一定出错)。所以可重入函数,并不使用全局变量或者是静态变量。但是可以使用栈空间, 2、不可重入函数:该函数的运行会为后续的调用者改变全局变量或者全局的静态变量,所以当信号中断时,在执行信号处理程序时,如果又一次运行该函数,就会改变全局的值,这样就会导致结果出错。所以这些函数是不可重入的。例如malloc函数就是不可重入函数。 3、线程安全的。 我们可以确定 pthread_mutex_lock函数显然是线程安全的,但是它不是异步可重入的,考虑下面的情况,有这么一段代码: pthread_mutex_lock(&gLock); change_some_thing(); pthread_mutex_unlock(&gLock); 假定有一个工作线程A运行到这段代码,调用了pthread_mutex_lock但是还没返回的时候,有个signal产生了,signal handler打断线程A执行,然后在signal handler的上下文中也运行到了这段代码(注意signal handler其实借用了线程A的上下文执行,这一点很像操作系统内核的中断处理),signal handler调用pthread_mutex_lock的时候,线程A的pthread_mutex_lock可能才执行了一半,因为pthread_mutex_lock不是异步可重入的,所以在signal handler的上下文中的pthread_mutex_lock调用很可能会破坏pthread_mutex_t的内部状态,导致程序死锁等异常行为。 所以说线程安全的函数不一定是可重入的。 4、使用加锁把不可重入的函数编程线程安全的。 如果一个函数的实现使用了全局或者静态变量,那么这个函数既不是可重入的,也不是线程安全的。 如果放宽条件,这个函数仍然用到了全局或者静态变量,但是在访问这些变量时,通过加锁来保证互斥访问,那么这个函数就可以变成线程安全的函数。但它此时仍然是不可重入的,因为通常加锁是针对不同线程的访问,对同一线程可能出现问题(发生信号软中断,signal handler中恰巧也执行了该函数)。 参考:https://www.zhihu.com/question/21526405       http://www.cnblogs.com/clover-toeic/p/3739308.html
    转载请注明原文地址: https://ju.6miu.com/read-1302212.html
    最新回复(0)