Python:跨线程共享类变量

led*_*uss 3 python python-multithreading

我在一个类的许多实例之间共享一个计数器(training_queue).该类继承了threading.Thread,因此它实现了run()方法.当我调用start()时,我希望每个线程都增加这个计数器,所以当它达到一个限制时,不再启动线程.但是,没有一个线程修改变量.这是代码:

class Engine(threading.Thread):

training_mutex = threading.Semaphore(MAX_TRAIN)
training_queue = 0
analysis_mutex = threading.Semaphore(MAX_ANALYSIS)
analysis_queue = 0
variable_mutex = threading.Lock()


def __init__(self, config):
    threading.Thread.__init__(self)
    self.config = config
    self.deepnet = None
    # prevents engine from doing analysis while training
    self.analyze_lock = threading.Lock()

def run(self):
    with self.variable_mutex:
        self.training_queue += 1
    print self.training_queue
    with self.training_mutex:
        with self.analyze_lock:
            self.deepnet = self.loadLSTM3Model()
Run Code Online (Sandbox Code Playgroud)

我使用Lock保护training_queue,因此它应该是线程安全的.但是,如果我总是打印它的值1.在这种情况下,线程如何影响变量范围?

luv*_*luv 10

您对线程之间如何共享状态的理解是正确的.但是,您使用实例属性"training_queue"而不是类属性"training_queue".

也就是说,您始终为每个新对象将training_queue设置为1.

例如:

import threading

class Engine(threading.Thread):
    training_queue = 0
    print_lock = threading.Lock()

    def __init__(self, config):
        threading.Thread.__init__(self)

    def run(self):
        with Engine.print_lock:
            self.training_queue += 1
            print self.training_queue

Engine('a').start()
Engine('b').start()
Engine('c').start()
Engine('d').start()
Engine('e').start()
Run Code Online (Sandbox Code Playgroud)

将返回:

1
1
1
1
1
Run Code Online (Sandbox Code Playgroud)

但:

import threading

class Engine(threading.Thread):
    training_queue = 0
    print_lock = threading.Lock()

    def __init__(self, config):
        threading.Thread.__init__(self)

    def run(self):
        with Engine.print_lock:
            Engine.training_queue += 1
            print self.training_queue

Engine('a').start()
Engine('b').start()
Engine('c').start()
Engine('d').start()
Engine('e').start()
Run Code Online (Sandbox Code Playgroud)

返回:

1
2
3
4
5
Run Code Online (Sandbox Code Playgroud)

注意self.training_queue与Engine.training_queue

顺便说一句.我认为+ =在python中应该是原子的所以我不会打扰锁.但是,在上面的示例中,没有使用锁来打印到stdout.

  • 这实际上有点误导。`+=`不是一个原子操作。它需要三行代码 - `__getattr__`、`variable = variable + 1` 和 `__setattr__`。 (2认同)