5

所以我有一个队列:

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中取出项目。"first"但是t-2线程可能会在线程可以获取"second"之前获取该项目t-1,从而使队列为空......但是当检查时,队列t-1self.process_q.empty()为空。所以t-1线程永远不会退出/完成并挂起。

如果我对进程 ID 进行 strace,我会得到以下信息:

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

我该如何解决这个问题???

4

2 回答 2

8

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

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

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

不是在所有线程上同步的。因此可能有超过 2 个线程(队列大小 = 2)通过 if 条件。两个线程正在从 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

守护进程

一个布尔值,指示此线程是否为守护线程 (True) 或不是 (False)。这必须在调用 start() 之前设置,否则会引发 RuntimeError。它的初始值继承自创建线程;主线程不是守护线程,因此在主线程中创建的所有线程默认为 daemon = False。

当没有活着的非守护线程时,整个 Python 程序退出。

通过将daemon-mode设置为true,程序会在队列为空(q.join())后退出。

于 2015-10-07T08:16:03.487 回答
-2

我遇到了同样的问题,并确定有一个“ python /usr/bin/goferd ”进程在 RHEL7 机器上消耗 100% CPU。

[root@RHELLINUXPROD~]# ps aux | grep -i 1268 根 1268 90.4 0.0 1030428 25304 ?Ssl Jun 04 111901:11 python /usr/bin/goferd --foreground

问题识别: 这个“/usr/bin/goferd”进程将与客户端机器上的 RedHat 卫星订阅相关。

这是 RedHat 卫星订阅代理“katello-ca-consumer-latest.noarch.rpm”的错误

解决方案:

临时解决方案:

找出你的 RHEL7 机器上安装的 katello 代理。

[root@RHELLINUXPROD~]# katello-ca-consumer-rhsat-i01.0-1.noarch katello-agent-1.5.3-7.el7sat.noarch

在客户端 RHEL7 机器上清理并取消注册 Redhat 订阅

*# 订阅管理器清理

订阅管理器取消注册*

从 RHEL7 客户端中删除已安装的 katello 代理

[root@RHELLINUXPROD~]# rpm -e katello-ca-consumer-rhsat-i01.0-1.noarch [root@RHELLINUXPROD~]# rpm -e katello-agent-1.5.3-7.el7sat.noarch

现在您可以看到使用“ps -ef | grep -i goferd”命令输出 python 进程已停止并且服务器 CPU 利用率变得正常。

再次重新安装 katello aganet 并将服务器订阅到 redhat 卫星。

永久解决方案:

您必须将卫星升级到最新版本,然后才能永久解决此问题。

感谢和问候 Namasivayam

于 2018-08-28T08:24:12.020 回答