Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5699840
  • 博文数量: 675
  • 博客积分: 20301
  • 博客等级: 上将
  • 技术积分: 7671
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-31 16:15
文章分类

全部博文(675)

文章存档

2012年(1)

2011年(20)

2010年(14)

2009年(63)

2008年(118)

2007年(141)

2006年(318)

分类: C/C++

2009-02-21 11:47:32

偶然看到CU上的一篇关于讨论的帖子,里面讨论了fork() in thread,里面有很多东西不是很明白,就自己研究了一下,才有了这篇心得。

fork() in thread
一个基本原则是:应当避免在pthread中使用fork(),除非你在新程序中立即执行exec()

这里最关键的一点就是:mutex的状态不会因为fork而发生变化,在parent中是locked的在child中也是locked的。

考虑下面的情况:
线程组A中有线程1和2,线程1中lock了一个mutex a;线程2调用了fork()创建了一个新的进程B,进程B中需要使用mutex a保护的数据,lock(mutex a)。这个时候就会出现问题,
线程2和线程1在同一个线程组里面,共享地址空间,线程1总会unlock(mutex a)的,那么线程2还是可以使用lock(mutex a)的(需要等到线程1调用unlock(mutex a))。但是对于进程B,
也拷贝了mutex a,但是是locked状态,又与线程组不同的地址空间,没有代码来unlock(mutex a),那么它就会hang在lock(mutex a)上面。

上面讨论的情况,可以用下面的流程图来表示:

        process A                         process B
thread 1            thread 2         
lock(mutex a)       
                    fork()      =====>     
                    lock(mutex a)        lock(mutex a)
unlock(mutex a)                          .....(hang)   <===== mutex a locked
                    ......
                    unlock(mutex a)       

参考2里面的一句话,实际上是sun的《多线程编程指南》里面的一段:
例如,假设当T2 fork 新进程时,T1 在进行打印,且对printf() 持有锁定。在子进程中,如果唯一的线程(T2) 调用printf(),则T2 将快速死锁。

刚开始怎么都不理解,后来看了《Programming With Posix Threads》才恍然大悟:
stdio一般使用静态存储空间进行buffer的存放,因此需要一些mutex或者是semphore来访问buffer,因此在stdio操作的mutex在fork_with_thread会引发问题。

再考虑上面的那段话:
T2调用fork()的时候,T1正在printf(),也就是说T1获得了mutex,T2新fork的进程也会得到已经locked的mutex,那么在T2新fork的进程中调用printf,尝试lock(mutex)的话,就会出现上面的问题(新进程hang在lock(mutex)上面)。


参考:
1.《Programming With Posix Threads》
2.fork_with_thread
http://iunknown.javaeye.com/blog/102767
3.Linux多线程编程和Linux 2.6下的NPTL


阅读(3028) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~