繁体   English   中英

在python中使用线程池时无法增加值

[英]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

如果要增加数字,可以将其存储在可变数据类型(例如listdict )中并操作该列表。

intdictionaries工作方式有所不同,我相信精通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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM