什么是可重入函数?
什么是可重入函数?
通常,可从维基百科引用对可重入性的定义:
计算机程序或例程被描述为可重入,如果在其前一个调用完成之前可以“安全地”再次调用它(即可以安全地同时执行)。为了是可重入的,计算机程序或例程必须:
1. 不包含任何静态(或全局)非常量数据。
2. 不返回指向静态(或全局)非常量数据的地址。
3. 只对调用者提供的数据进行操作。
4. 不依赖于锁定单例资源。
5. 不修改自身的代码(除非在自己的独特线程存储中执行)。
6. 不调用非可重入的计算机程序或例程。
“安全地”是如何定义的?
如果一个程序可以“安全地同时执行”,是否意味着它是可重入的?
在检查代码的可重入能力时,这六个要点之间有什么共同之处?
此外,
1. 所有递归函数都是可重入的吗?
2. 所有线程安全的函数都是可重入的吗?
3. 所有递归和线程安全的函数都是可重入的吗?
在撰写这个问题时,我想到了一件事:
像“可重入性”和“线程安全性”这样的术语是否绝对存在,即它们是否具有固定的具体定义?如果不是,那么这个问题就没有太多意义。
什么是可重入函数?
可重入函数是指能够在多个线程或递归调用中同时执行而不会相互干扰的函数。一个可重入函数必须满足以下条件:
1. 不使用或修改全局或静态变量。
2. 不使用或修改共享资源,如文件或网络连接等。
3. 不使用或修改静态缓冲区。
4. 通过参数传递数据,而不是使用全局变量。
5. 不使用非可重入的函数。
6. 不依赖于中断或信号处理。
递归函数和线程安全函数不一定是可重入的,因为它们可能会使用全局或静态变量,或者依赖于非可重入的函数。
如果两个递归调用同时访问相同的全局或静态变量,它们可能会相互干扰,导致错误的结果。
如果一个函数是线程安全的,意味着在并发调用时不会出现错误,但它可能通过使用互斥锁来阻塞第二个调用的执行,从而保证只有一个调用在运行。可重入性要求函数能够同时执行而不会相互干扰。
因此,并不是所有的递归函数和线程安全函数都是可重入的。
解决方法是遵循上述条件,确保函数不会使用或修改全局或静态变量,并通过参数传递数据。如果需要使用共享资源,可以通过互斥锁或其他同步机制来保护。此外,还可以使用局部变量代替静态缓冲区,并避免使用非可重入的函数。
总结起来,可重入函数是能够在多个线程或递归调用中同时执行而不会相互干扰的函数。为了实现可重入性,函数必须遵循一定的规则,如不使用全局或静态变量,不使用共享资源,不使用静态缓冲区等。如果一个函数是递归的或线程安全的,并不意味着它就是可重入的,它可能还需要满足其他条件。解决方法是根据规则修改函数的实现,确保它满足可重入性的要求。
什么是可重入函数?
可重入函数是指可以在同一时间被多个线程安全地执行的函数。然而,并不是所有线程安全的函数都是可重入的,反之亦然。
一个函数是否可重入,取决于以下几个因素:
1. 函数是否具有状态,即是否访问全局变量或类成员变量;
2. 函数是否可以被多个线程同时调用,或者在进程执行过程中是否可能出现多次调用(如函数可以直接或间接地调用自身)。
如果一个函数具有状态或可以被多个线程同时调用,那么它很可能不是可重入的。
为了确保函数是可重入的,可以采取以下几种方法:
1. 确保函数没有状态,只使用参数、局部变量和无状态的其他函数,并在需要返回数据时返回副本而不是引用。
2. 确保对象的方法是“递归安全”的,即在调用方法A后可以立即调用方法B而不会破坏整个对象。
3. 确保对象的内部数据不被其他代码访问,以防止数据被意外修改。
4. 告知用户对象不是线程安全的,用户在多个线程之间共享对象时需要使用互斥量进行保护。
5. 如果同一个线程可能多次使用同一资源,则使用递归互斥量以确保对资源的修改是原子的。
在实际编码中,如果正确地划分代码,并遵循上述方法,就可以避免可重入性问题。
虽然判断一个函数是否是可重入的可能有一定困难,但是通过对代码的分析和设计,可以尽量确保函数的可重入性。
参考资料:[Stack Overflow](https://stackoverflow.com/questions/2627396)