Value
действительно изменчив; вы указываете нужный тип данных из модуля ctypes
и затем его можно изменить. Вот полный рабочий скрипт, который демонстрирует это:
from time import sleep
from ctypes import c_int
from multiprocessing import Value, Lock, Process
counter = Value(c_int) # defaults to 0
counter_lock = Lock()
def increment():
with counter_lock:
counter.value += 1
def do_something():
print("I'm a separate process!")
increment()
Process(target=do_something).start()
sleep(1)
print counter.value # prints 1, because Value is shared and mutable
РЕДАКТИРОВАТЬ: Luper правильно указывает в комментарии ниже, что Value
значения заблокированы по умолчанию. Это правильно в том смысле, что даже если присваивание состоит из нескольких операций (например, присваивание строки, которая может содержать много символов), это присваивание является атомарным. Однако при увеличении счетчика вам все равно понадобится внешняя блокировка, как показано в моем примере, поскольку приращение загружает текущее значение, а затем увеличивает его, а затем присваивает результат обратно Value
.
Таким образом, без внешней блокировки вы можете столкнуться со следующими обстоятельствами:
- Процесс 1 читает (атомарно) текущее значение счетчика, затем увеличивает его
- до того, как Процесс 1 сможет присвоить увеличенный счетчик обратно
Value
, происходит переключение контекста
- Процесс 2 считывает (атомарно) текущее (неинкрементное) значение счетчика, увеличивает его и присваивает увеличенный результат (атомарно) обратно
Value
- Процесс 1 назначает свое увеличенное значение (атомарно), отклоняя приращение, выполняемое Процессом 2