系统相关
首页 > 系统相关> > Python:进程在futex(0x2a5fcc0,FUTEX_WAIT_PRIVATE,0,NULL在多线程中挂起

Python:进程在futex(0x2a5fcc0,FUTEX_WAIT_PRIVATE,0,NULL在多线程中挂起

作者:互联网

所以我有一个队列:

q = Queue.Queue()

我在里面放一些东西.

items = ["First", "Second"]
for val in items:
    q.put(val)

我正在生成15个线程.

for i in range(15):
   tname = 't-%s' % i
   t = my_thread(some_func, q, tname)
   t.start()

q.join()

my_thread类的外观如下:

class my_thread(threading.Thread):
    def __init__(self, some_func, q_, name=''):
       threading.Thread.__init__(self)
       self.func = some_func
       self.process_q = q_
       self.name = name
       self.prefix = name


    def run(self):
       stime = time.time()
       logging.info('%s thread staring at : %s' % (threading.currentThread().getname(), time.ctime(stime)))
       while True:
           if self.process_q.empty():
               break
           queue_item = self.process_q.get()
           self.name = self.prefix + '-' + queue_item
           try:
               #run the function
           except Exception as e:
               logging.error('Caught some error')
           finally:
               self.process_q.task_done()


       endTime = time.time()
       logging.info('%s thread finished at: %s' % (threading.currentThread().getName(), time.ctime(endTime)))

如果我看一下日志,我看到的是两个或多个线程同时访问队列,而当队列为空时,while循环不会中断.

假设t-0线程已从队列中取出“第一”项目.
但是t-2线程可能先于t-1线程获取“第二”项目,从而使队列为空…但是当t-1进行self.process_q.empty()检查时,队列就没有空的.因此,t-1线程永远不会退出/结束并挂起.

如果我对进程ID进行跟踪,则会得到以下结果:

Process 13307 attached
futex(0x2a5fcc0, FUTEX_WAIT_PRIVATE, 0, NULL

我该如何解决???

解决方法:

您的线程随机挂在阻塞的self.process_q.get()函数中. ->种族条件

此刻,线程已启动,队列不为空.
代码部分…

...
if self.process_q.empty():
    break
queue_item = self.process_q.get()
...

未在所有线程上同步.因此可以通过if条件超过2个线程(队列大小= 2).两个线程正在从self.process_q.get()函数获取结果,而其他线程正在阻塞并等待队列中的结果.

直到所有非守护进程线程都完成后,python程序才能退出.因此它永远挂起.

考虑将线程设置为守护程序模式:

for i in range(15):
    tname = 't-%s' % i
    t = my_thread(some_func, q, tname)
    t.setDaemon(True)
    t.start()

https://docs.python.org/2/library/threading.html#threading.Thread.daemon开始:

daemon

A boolean value indicating whether this thread is a daemon thread
(True) or not (False). This must be set before start() is called,
otherwise RuntimeError is raised. Its initial value is inherited from
the creating thread; the main thread is not a daemon thread and
therefore all threads created in the main thread default to daemon =
False.

The entire Python program exits when no alive non-daemon threads are left.

通过将守护程序模式设置为true,程序将在队列为空之后退出(q.join()).

标签:multithreading,queue,futex,python
来源: https://codeday.me/bug/20191027/1947412.html