使用消息队列的线程同步不按顺序进行

时间:2017-10-13 19:11:31

标签: python multithreading python-2.7 message-queue python-multithreading

以下代码来自Raymond's Pycon keynotes on cuncurrency,精彩演示。它有点长,所以我从问题开始:

  • 如果消息一起添加到队列,并且两者都应该在线程被认为完成之前打印出来,那么它们如何被打印出来?在线程初始化之间添加100ms的延迟解决了这个问题,并且输出正如预期的那样。

-

import Queue, time

counter_queue = Queue.Queue()
counter = 0

def counter_manager():
    # I have EXCLUSIVE rights to update the counter variable
    global counter

    while True:
        increment = counter_queue.get()
        counter += 1
        print_queue.put(['The count is {}\n'.format(counter),
                         '----------\n'])
        counter_queue.task_done()

t = threading.Thread(target=counter_manager)
t.daemon = True
t.start()
del t


print_queue = Queue.Queue()

def print_manager():
    # I have EXCLUSIVE rights to call the print keyword
    while True:
        job = print_queue.get()
        for line in job:
            print line
        print_queue.task_done()

t = threading.Thread(target=print_manager)
t.daemon = True
t.start()
del t

def worker_threads():
    counter_queue.put(1)

print_queue.put(['Starting up.. with message queues'])
worker_threads = []
for i in range(10):
    t = threading.Thread(target=worker)
    worker_threads.append(t)
    t.start()
    # time.sleep(0.1)
for t in worker_threads:
    t.join()

counter_queue.join()
print_queue.put(['Finishing up'])
print_queue.join()

它使用counter_managerprint_queue作为守护进程来接收来自工作线程的消息,并按顺序执行它们。据我了解,这应该保留执行的顺序。但是,我得到以下输出:

Starting up.. with message queues
The couns is 1The couns is 2

--------------------

The couns is 3
 ----------The couns is 4
 The couns is 5
The couns is 6
----------
----------
----------
The couns is 7

----------The couns is 8

The couns is 9----------

----------The couns is 10

----------
Finishing up

计数器正确递增,打印消息仍然被破坏。

如果我取消注释sleep语句,则线程初始化会延迟100ms并且输出正确

Starting up.. with message queues
 The couns is 1
----------
The couns is 2
----------
The couns is 3
----------
The couns is 4
----------
The couns is 5
----------
The couns is 6
----------
The couns is 7
----------
The couns is 8
----------
The couns is 9
----------
The couns is 10
----------
Finishing up

使用队列,打印应该是有序的。这不正确吗?

工人代码

def worker():
    global counter

    counter += 1
    print 'The couns is {}'.format(counter)  # read the var (race cond.)
    print '----------'

1 个答案:

答案 0 :(得分:2)

我无法复制此问题。为了让它运行,我添加了threading导入,并将worker_threads函数重命名为worker

输出有“couns”但你的代码表示“count”。你能验证你提供的输出和代码是否重合?

您的输出似乎只在行级别交错。

我想知道代码的先前版本是否在.put中有两个不同的counter_manager s(非原子),后来合并为一个.put多行?