NullPointerException
s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException
. Они наиболее распространены, но другие способы перечислены на странице NullPointerException
javadoc.
Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException
, be:
public class Example {
public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}
}
В первой строке внутри main
я явно устанавливаю ссылку Object
obj
равной null
. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException
, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.
(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)
Проблема заключается в том, что переменная counter
не разделяется между вашими процессами: каждый отдельный процесс создает собственный локальный экземпляр и увеличивает его.
См. в этом разделе документацию для некоторых методов, которые вы можете использовать для совместного использования состояния между вашими процессами. В вашем случае вы можете поделиться экземпляром Value
между вашими работниками
. Вот рабочая версия вашего примера (с некоторыми фиктивными входными данными). Обратите внимание, что он использует глобальные значения, которые я действительно пытался бы избежать на практике:
from multiprocessing import Pool, Value
from time import sleep
counter = None
def init(args):
''' store the counter for later use '''
global counter
counter = args
def analyze_data(args):
''' increment the global counter, do something with the input '''
global counter
# += operation is not atomic, so we need to get a lock:
with counter.get_lock():
counter.value += 1
print counter.value
return args * 10
if __name__ == '__main__':
#inputs = os.listdir(some_directory)
#
# initialize a cross-process counter and the input lists
#
counter = Value('i', 0)
inputs = [1, 2, 3, 4]
#
# create the pool of workers, ensuring each one receives the counter
# as it starts.
#
p = Pool(initializer = init, initargs = (counter, ))
i = p.map_async(analyze_data, inputs, chunksize = 1)
i.wait()
print i.get()
Класс Faster Counter без использования встроенного замка значения дважды
class Counter(object):
def __init__(self, initval=0):
self.val = multiprocessing.RawValue('i', initval)
self.lock = multiprocessing.Lock()
def increment(self):
with self.lock:
self.val.value += 1
@property
def value(self):
return self.val.value
https://eli.thegreenplace.net/2012/01/04/shared-counter-with -pythons-multiprocessing https://docs.python.org/2/library/multiprocessing.html#multiprocessing.sharedctypes.Value https://docs.python.org /2/library/multiprocessing.html#multiprocessing.sharedctypes.RawValue
Класс Counter без ошибки состояния гонки:
class Counter(object):
def __init__(self):
self.val = multiprocessing.Value('i', 0)
def increment(self, n=1):
with self.val.get_lock():
self.val.value += n
@property
def value(self):
return self.val.value
joblib
s Parallel
(код в этом ответе не работает с joblib
), см. github.com/davidheryanto/etc/blob/master/python-recipes/…
– Dan Nissenbaum
13 January 2018 в 23:04
return self
к функции increment
, чтобы включить цепочку
– Boris Gorelik
24 May 2018 в 05:00
counter.value += 1
не является атомарным между процессами, поэтому значение будет неправильным, если запустить достаточно долго с несколькими процессами – Eli Bendersky 31 December 2011 в 12:25Lock
должен окружать инструкциюcounter value += 1
. См. stackoverflow.com/questions/1233222/… – A-B-B 17 July 2012 в 20:32with counter.get_lock()
, а неwith counter.value.get_lock():
– Jinghao Shi 14 January 2016 в 19:23counter.value.get_lock()
будет производитьAttributeError: 'int' object has no attribute 'get_lock'
– Samuel 30 March 2016 в 07:41