线程池的陷阱

使用线程池要小心,一不小心就会导致程序挂死。举例说明这种情况。

线程池中有一个同步队列存放数据,多个线程取队列中的数据去处理,数据的类型可能有多个,所以每种数据类型对应一个处理函数,假设某种数据的处理函数会把线程阻死,这时就悲剧了,这个阻死会蔓延到线程池的所有线程,最后线程池中所有的线程都挂死了,程序也挂死了。因为线程池的线程是不停的切换去处理数据的,凡是遇到会挂死线程的数据时,线程会一个个死掉,直到所有的线程挂死。

解决办法是:

一、一个类型的数据一个线程或者多个类型的数据一个线程,这样某个类型的数据处理导致线程挂死,其它线程还能正常运行,不会导致程序挂死。

二、线程池中加超时处理,超时处理就不会挂死线程。

使用线程池一定要保证线程处理函数不会挂死,否则整个程序都会挂死了。线程池内部的线程函数需要加超时处理,一个简单的处理方法是通过一个临时线程去控制该函数是否超时。原来的处理逻辑

while (m_running)        
{

        Task task; m_queue.Take(task);
if (task) { task() } } 改成带超时的处理逻辑 while (m_running) { Task task; m_queue.Take(task); if (task) { boost::thread thd(task); if(thd.timed_join(boost::posix_time::seconds(5)))
          {   cout
<<"没有超时"<<endl;
          }
else
          {
cout<<"超时"<<endl;
            //要做超时处理,这时要释放导致超时的资源,比如关闭socket或者关闭数据库
            //通知应用层做相应的处理如CloseSocket(),CloseDB()
          } } }

 超时处理时要把导致线程函数挂死的资源释放,比如关闭socket或者关闭数据库,让挂死的线程能退出。

注意:这里只是一个程序的容错保证,并不解决根本问题,解决根本问题还是要把导致线程卡死的函数的bug解决。

posted on 2013-07-30 14:40  qicosmos(江南)  阅读(1461)  评论(0编辑  收藏  举报

导航