第十二章中的线程属性和同步属性已分在前几篇中说明,本篇继续说第十二章中后面的内容。
首先,reentrancy,可重入的概念【wikipedia:reentrancy】:
In computing, a computer program or subroutine is called reentrant if it can be interrupted in the middle of its execution and then safely called again ("re-entered") before its previous invocations complete execution.
信号处理中有可重入的概念,多线程中也有可重入的概念,在我的理解中它们的本质是一样的,关键在于“re-entered”这个词,它既可以理解为再次进入(信号处理中的中断),也可以理解为多次进入(多线程同时访问),只要“re-”的过程中是safe的,那么它就是reentrant的。
(ps:我查了很多资料,大部分中文资料只停留在表面讲解“可重入”的概念,更有说递归函数就是可重入函数,简直一派胡言!stack overflow上有个perfect的资料,简直就是perfect!【Stack Overflow:What exactly is a reentrant function? http://stackoverflow.com/questions/2799023/what-exactly-is-a-reentrant-function】,如果你有耐心把他说的所有的都看完呢,那肯定会受益匪浅!)
典型的non-reentrant函数有下面特征:
(a)使用静态数据结构
(b)调用malloc或free
(c)使用标准I/O函数
其实,这些关键在于理解,而不在于死记硬背。上面为什么是non-reentrant的?是因为它们有global的结构,使用了lock-based synchronization(基于锁的同步机制)。(【Stack overflow:http://stackoverflow.com/questions/3941271/why-are-malloc-and-printf-said-as-non-reentrant】)
想一想,malloc()使用了global memory,printf()使用了global buffer,我们在“单线程”的环境下,通过下面的例子来了解“lock-based synchronization”为什么是non-reentrant的:
malloc(); //initial call lock(memory_lock); //acquire lock inside malloc implementation signal_handler(); //interrupt and process signal malloc(); //call malloc() inside signal handler lock(memory_lock); //try to acquire lock in malloc implementation // DEADLOCK! We wait for release of memory_lock, but // it won't be released because the original malloc call is interrupted看,malloc时锁住了memory_lock,中断时,signal_handler又malloc时,又要对memory_lock加锁,产生了死锁!
既然,我们明白了信号处理中的non-reentrant,那我们来看看下面两个概念:async-signal safe(异步信号安全)与thread-safe(线程安全)。
async-signal safe:函数对“异步信号处理程序的重入”是安全的;
thread-safe:函数对“多个线程的重入”是安全的。
好吧,其实完全不必把thread-safe和reentrant的概念混合在一起,这样只会徒增麻烦,我们换一种方式来理解“线程安全”:
thread-safe:如果一个函数在同一个时间点可以被多个线程安全地调用,那么它就是线程安全的。
那么 保证thread-safe的方法有哪些呢?
无论是(a.避免共享状态)re-entrancy、thread-local storage,还是(b.无法避免共享则异步机制)mutual exclusion、atomic operations,都可以保证thread-safe。
看这里【Wikipedia,thread safety:http://en.wikipedia.org/wiki/Thread_safety】。
好啦,关于可重入与线程安全就讲这些~