您的位置:首页 > 编程语言

unix环境高级编程-线程控制(2)

2016-08-03 20:13 239 查看
重入:

线程在遇到重入问题时与信号处理程序是类似的,在两种情况下,多个控制线程在相同时间有可能调用相同的函数

如果一个函数在相同的时间点可以被多个线程安全的调用,就认为该函数是线程安全的。除了下表的函数,其他函数都是线程安全的



如果一个函数对多个线程来说是可重入的,就称这个函数是线程安全的,但并不能说明对信号处理程序来说该函数就是可重入的,如果函数对异步信号处理程序的重入是安全的,那么就可以说函数是异步信号安全的。

线程特定数据:

也称线程私有数据,是存储和查询某个特定线程相关数据的一种机制,希望每个线程访问自己单独的数据副本,而不需担心其他线程同步访问问题。

这样做的好处有两个:

1.有时需要维护基于每线程的数据

2.它提供给了让基于进程的接口适应多线程环境的机制。一个很明显的例子就是errno,以前的接口把errno定义为进程上下文中全局可访问的整数,系统调用和库例程在调用或执行失败时设置errno,把它作为操作失败的附属结果,为了让线程也能使用这些基于进程的系统调用和库调用,errno重新定义为线程私有数据,这样一个线程做了重置errno操作也不会影响到进程中其他线程errno值。

线程通常使用malloc为线程特定数据分配内存,析构函数释放已分配内存,若线程在没有释放内存之前就退出了,这块内存就会丢失,该进程出现内存泄漏。

取消选项:

有两个线程属性并没有包含在pthread_attr_t结构中,,是可取消状态和可取消类型,这两个属性影响着线程在响应pthread_cancel函数调用时所呈现的行为。

可取消状态属性可以是PTHREAD_CANCEL_ENABLE,也可以是PTHREAD_CANCEL_DISENABLE,线程可以调用pthread_setcancelstate修改它的可取消状态。

pthread_cancel调用并不等待线程终止,在默认情况下,线程在取消请求发出以后还是会继续运行,直到线程到达某个取消点,取消点是线程检测它是否被取消的一个位置,如果取消了,则按照请求行事。

线程启动时默认的可取消状态是PTHREAD_CANCEL_ENABLE,当状态设置为PTHREAD_CANCEL_DISENABLE,对pthread_cancel的调用并不会杀死线程,相反取消请求对这个线程来说还处于挂起状态,当取消状态再次变为PTHREAD_CANCEL_ENABLE,线程将在下一个取消点上对所有挂起的取消请求进行处理。

下表是POSIX定义的取消点



线程和信号:

每个线程都有自己的信号屏蔽字,但是信号的处理是进程中所有线程共享的,当某个线程修改了某个给定信号之后,所有的线程都必须共享这个处理行为的改变,如果一个线程选择忽略某个给定信号,那么另一个线程就可以通过以下两种方式撤销上述线程的信号选择:恢复信号的默认行为,或者为信号设置一个新的信号处理程序。

过程中的信号是递送到单个进程的,如果一个信号与硬件故障相关,那么该信号一般会被发送到引起该事件的线程中去,而其他信号则被发送到任意一个进程。

线程和fork:

当线程调用fork时,为子进程创建了整个进程地址空间的副本,子进程通过继承整个地址空间的副本,还从父进程那继承了每个互斥量、读写锁和条件变量的状态,如果父进程包含一个以上的线程,子进程在fork返回后,如果紧接着不是马上调用exec的话,就需要清理锁状态。

在子进程内部,只存在一个线程,它是由父进程调用fork的线程的副本得到的,如果父进程中的线程占有锁,子进程将同样占有这些锁,问题是子进程不包含占有锁的线程的副本,因此子进程无法知道它占有了哪些锁,需要释放哪些锁。

如果子进程从fork返回以后马上调用其中一个exec函数,就可避免这样的问题,因为旧的地址空间被丢弃,锁的状态无关紧要,但如果子进程要继续做处理工作的话,这种策略就行不通。POSIX规定,在fork返回和子进程调用其中一个exec函数之间,子进程只能调用异步信号安全的函数,这就限制了在调用exec之前子进程能做什么。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: