Блокировка не блокирует многопроцессорность - PullRequest
1 голос
/ 11 апреля 2020
from multiprocessing import Process, Lock, current_process
import requests as r

def get(lista, lista_lock):
    lista_lock.acquire()
    print(f"PID: {current_process().name} ID liste: {id(lista)}")
    temp = lista[:1]
    del lista[:1]
    lista_lock.release()
    res = r.get(*temp)
    print(f"PID: {current_process().name} ->  {res.url}")

if __name__ == "__main__":
    lista = ["https://www.index.hr", "https://www.24sata.hr"]

    lista_lock = Lock() 

    p1 = Process(target=get, args=(lista, lista_lock))
    p2 = Process(target=get, args=(lista, lista_lock))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

    print(f"lista ID: {id(lista)}")

В результате я получаю ...

PID: Process-1 ID liste: 140292127163144
PID: Process-2 ID liste: 140292127163144
PID: Process-1 ->  https://www.index.hr/
PID: Process-2 ->  https://www.index.hr/
lista ID: 140292127163144

Каждый процесс должен был получить разные ссылки, но они получили одинаковые. Кажется, замок не работает. Может кто-нибудь, пожалуйста, помогите мне.

У меня есть еще 1 вопрос относительно ID "lista". Если это разные процессы, почему они имеют одну и ту же переменную "lista"? Я думал, что каждый процесс получает свою собственную копию данных.

1 Ответ

1 голос
/ 11 апреля 2020

В unix -подобных системах Process разветвляет подпроцесс с представлением родительского пространства памяти с копией при записи. На Windows он вызовет новый процесс python и попытается выбрать / отнять соответствующее состояние для дочернего элемента. В обоих случаях дочерний элемент получает полный lista, и любые всплывающие или удаляемые элементы действительны только для этого подпроцесса. (В вашем случае ваш код не будет работать на Windows, потому что блокировки не могут быть обработаны).

Вы можете использовать multiprocessing.Manager для создания представлений списка, которые проксируются в двух процессах. но это обычно не очень эффективно. Вместо этого используйте Pool, он уже создан для того, что вы хотите.

import multiprocessing as mp
import requests as r

def get(item):
    print(f"PID: {mp.current_process().name} item: {item}")
    res = r.get(item)
    print(f"PID: {mp.current_process().name} ->  {res.url}")

if __name__ == "__main__":
    lista = ["https://www.index.hr", "https://www.24sata.hr"]

    pool = mp.Pool(min(len(lista), mp.cpu_count())) 
    pool.map(get, lista)
    pool.close()
    pool.join()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...