自我加入线程池:我的竞争条件在哪里?

时间:2015-10-07 08:36:30

标签: python multithreading race-condition python-multithreading worker

由于我在工作中使用了类似的模式,因此我决定编写一个类,通过作业队列/线程来抽象非常简单的工作并发。我知道已经有一些东西可以解决这个问题,但我也希望利用这个机会来磨练我的多线程技能。

我给自己的主要挑战是,我希望这能让流程完成,即使它们没有被Queue.join()明确阻止。 "流程结束"由输入函数定义返回值(或None)。我试图实现这一目标的方法是让每个作业创建自己的结果队列rq,然后在非守护程序线程中由_wait_for_results检查,这会阻止自动退出rq中的工作人员填写add_to_queue之前的所有其他守护程序线程。

以下是完整的课程:

class EasyPool(object):
    def __init__(self, concurrency, always_finish=True):
        def add_to_queue(q):
            while True:
                func_data, rq = q.get()
                func, args, kwargs = func_data
                if not args:
                    args = []
                if not kwargs:
                    kwargs = {}
                result = func(*args, **kwargs)
                rq.put(result)
                q.task_done()

        self.rqs = []
        self.always_finish = always_finish
        self.q = Queue(maxsize=0)
        self.workers = []
        for i in range(concurrency):
            worker = Thread(target=add_to_queue, args=(self.q,))
            self.workers.append(worker)
            worker.setDaemon(True)
            worker.start()

    def _wait_for_results(self, rq):
        rq.not_empty.acquire()
        rq.not_empty.wait()
        rq.not_empty.notify()
        rq.not_empty.release()

    def add_job(self, func, *args, **kwargs):
        rq = Queue()
        if self.always_finish:
            blocker = Thread(target=self._wait_for_results, args=(rq,))
            blocker.setDaemon(False)
            blocker.start()
        to_add = []
        [ to_add.append(i) if i else to_add.append(None) for i in [func, args, kwargs] ]
        self.q.put((to_add, rq))
        return rq.get

当通过.add_job实例方法创建作业时,它会立即返回类似于promise的对象,该对象是对结果队列的.get方法的引用。我面临的问题是,.get_wait_for_results方法之间似乎存在竞争条件。我认为答案可能涉及锁定或条件,但我不确定。非常感谢任何帮助:)

0 个答案:

没有答案
相关问题