[英]cannot increment value when using threadpool in python
我正在使用Python线程池(Python配方)提供的类来模拟线程池。 我试图在功能test
增加值counter
。 问题在于它仍然为0
。 我使用的lock
在“这个简单的python代码线程是否安全吗?”中进行了解释,但仍然无法正常工作。
#! /usr/bin/python
# -*- coding: utf-8 -*-
from Queue import Queue
from threading import Thread
import threading
lock = threading.Lock()
class Worker(Thread):
"""Thread executing tasks from a given tasks queue"""
def __init__(self, tasks):
Thread.__init__(self)
self.tasks = tasks
self.daemon = True
self.start()
def run(self):
while True:
func, args, kargs = self.tasks.get()
try: func(*args, **kargs)
except Exception, e: print e
self.tasks.task_done()
class ThreadPool:
"""Pool of threads consuming tasks from a queue"""
def __init__(self, num_threads):
self.tasks = Queue(num_threads)
for _ in range(num_threads): Worker(self.tasks)
def add_task(self, func, *args, **kargs):
"""Add a task to the queue"""
self.tasks.put((func, args, kargs))
def wait_completion(self):
"""Wait for completion of all the tasks in the queue"""
self.tasks.join()
def exp1_thread(counter):
with lock:
print counter
counter = counter + 1
def test():
# 1) Init a Thread pool with the desired number of threads
pool = ThreadPool(6)
counter = 0
for i in range(0, 10):
pool.add_task(exp1_thread,counter)
# 3) Wait for completion
pool.wait_completion()
if __name__ == "__main__":
test()
counter 0
counter 0
counter 0
counter 0
counter 0
counter 0
counter 0
counter 0
counter 0
counter 0
之所以得到全零是因为整数计数器将按值传递给线程。 每个线程都会收到计数器的副本,然后进入城镇。
您可以通过找到一种通过引用传递值的方法来解决此问题。
选项1.将计数器定义为您要传递的列表:
def exp1_thread(counter):
with lock:
print counter[0]
counter[0] = counter[0] + 1
def test():
# 1) Init a Thread pool with the desired number of threads
pool = ThreadPool(6)
counter = [0]
for i in range(0, 10):
pool.add_task(exp1_thread, counter)
# 3) Wait for completion
pool.wait_completion()
选项2.创建一个您经过的对象。
class Counter:
def __init__(self, initial_count):
self.count = initial_count
def exp1_thread(counter):
with lock:
print counter.count
counter.count = counter.count + 1
def test():
# 1) Init a Thread pool with the desired number of threads
pool = ThreadPool(6)
counter = Counter(0)
for i in range(0, 10):
pool.add_task(exp1_thread, counter)
# 3) Wait for completion
pool.wait_completion()
这与线程无关。 实际原因是int
在Python中是不可变的。 仅增加一个int
函数将不会达到预期的效果。
def inc(x):
x +=1
y = 0
inc(y)
print y # 0
如果要增加数字,可以将其存储在可变数据类型(例如list
或dict
)中并操作该列表。
int
与dictionaries
工作方式有所不同,我相信精通Python逻辑的人可以解释其中的区别。 这是我通常使用的逻辑,并且有效。 正如我刚刚意识到的那样,这是因为您要传递对象(字典,列表等),而不是值本身。
要么将变量声明为全局变量(但要小心),要么使用说一个字典,该字典具有用于不同线程的单独的键槽,并在末尾对其求和。
from threading import *
from time import sleep
myMap = {'counter' : 0}
class worker(Thread):
def __init__(self, counterMap):
Thread.__init__(self)
self.counterMap = counterMap
self.start()
def run(self):
self.counterMap['counter'] += 1
worker(myMap)
sleep(0.2)
worker(myMap)
sleep(0.2)
print(myMap)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.