考虑POSIX对可重入性的扩展定义:
在POSIX.1c中,"可重入函数"被定义为Effect,当两个或多个线程调用时,保证是if每个线程一个接一个地执行函数未定义顺序,即使实际执行是交错的"(ISO/IEC2.2.2 9945:1 - 1996,§)。
来源:http://www.unix.org/whitepapers/reentrant.html
由于线程安全函数序列化并发执行,因此"每个线程以未定义的顺序一个接一个地执行函数,即使实际执行是交错的",这是否意味着线程安全函数是可重入的(仅考虑POSIX定义)?
不,线程安全的函数不一定是可重入的。
例如,考虑一个具有某种内部状态的函数,该状态由互斥锁保护,从而使其成为线程安全的。但是,如果从同一线程重新可入调用该函数,则会发生死锁。此类函数的一个常见示例是malloc();Malloc是线程安全的,但不可重入,这就是为什么你不应该在信号处理程序中调用Malloc,例如线程安全代码不需要序列化并发执行,因此我要说,根据您引用的POSIX定义,线程安全函数不需要可重入。
考虑下面的例子。你有两个线程安全函数:
void inc_count(struct counter* cnt);
int get_count(struct counter* cnt);
可以使用这两个函数定义另一个线程安全函数:
inc inc_and_get_count(struct counter* cnt) {
inc_count(cnt);
return get_count(cnt);
}
该函数的契约不能保证返回值等于inc_count()设置的值,它可以更大,但该函数仍然是线程安全的。
但是根据定义,它不是可重入的,从两个不同的线程调用该函数可以返回相同的值,如果执行是序列化的,则永远不会出现这种情况。
No。可重入性和线程安全性是函数的两个正交属性。POSIX.1c对可重入函数的定义并不意味着线程安全,因为函数可能是可重入的、线程安全的、两者都是或两者都不是。可重入函数只保证调用不会通过修改其他调用所依赖的状态而相互干扰,而不保证这些调用一定是线程安全的。