线程安全
如果一个函数在同一时刻可以被多个线程调用而最终结果正确,就称该函数是线程安全的。
线程安全问题都是由共享的资源,如全局变量、静态变量、IO等引起的。
- 一个函数如果不需要访问共享资源,那么为调用该函数的每个线程提供数据副本即可,该函数是线程安全的
- 一个函数如果访问的是只读的共享资源,那么该函数是线程安全的;
- 一个函数如果访问的是非只读的共享资源,那么需要利用互斥锁等提供线程同步,以确保程序以确定的方式(即串行)操作。
可重入函数
可以被中断而不会引起执行结果有二义性的函数。可重入函数具有以下特点
- 不在函数内部使用或返回静态或全局数据,只使用自己栈上的数据
- 不调用不可重入函数(如malloc()函数和标准IO函数等)
- 基本上也不能调用标准IO库,因为标准IO库的很多实现都以不可重入的方式使用全局
不可重入举例:
某进程或线程正在执行函数fun(),突然接收到一个信号sig, 此时需要暂停执行fun(),转去执行sig信号的处理函数sig_handler(),而有可能在sig_handler()中也调用了函数fun(). 当sig_handler()执行结束后,CPU会从原来fun()被打断的地方继续往下执行。如果fun()函数是可重入的,那么多次调用fun()函数的执行结果没有二义性,从而2次调用fun()的结果都是正确的预期结果。
线程安全和可重入的比较
可重入函数一定是线程安全的,而线程安全的不一定是可重入的。
因为线程安全的函数可能其中用到了锁,而对此函数中断,再在中断处理函数中使用到了同样的锁,则会引起死锁,因此不可重入。