Desarrollo multiproceso de Python (1)

 

Usar objetos Lock y RLock

  Si varios subprocesos modifican conjuntamente una determinada información, pueden producirse resultados impredecibles. Para garantizar la precisión de los datos, es necesario modificar varios subprocesos sincrónicamente. En el programa Python, use el objeto Lock y RLock

Se puede lograr una sincronización de subprocesos simple. Ambos objetos tienen métodos de adquisición y liberación. Para los datos que requieren que funcione solo un subproceso a la vez, puede colocar su operación entre los métodos de adquisición y liberación.

La ventaja de los subprocesos múltiples es que puede ejecutar múltiples tareas al mismo tiempo (sentirse así), pero cuando los subprocesos necesitan compartir datos, puede haber problemas con los datos que no están sincronizados. El siguiente código demuestra el uso de RLock para lograr la sincronización de subprocesos.

import threading 
import time 
class mt (threading.Thread): 
    def run (self): 
        global x 

        lock.acquire () 
        for i in range (5): 
            x + = 10 
        time.sleep (1) 
        print (x) 
        lock.release () 

x = 0 
lock = threading.RLock () 

def main (): 
    thrs = [] 
    para el elemento en el rango (8): 
        thrs.append (mt ()) 

    para el elemento en thrs: 
        item.start () 
if __name__ = = '__main__': 
    main ()

En el ejemplo anterior, se personaliza una clase de subproceso mt con un bloqueo para acceder a la variable global x, y se inicializan 8 subprocesos en la función principal main () para modificar x. Al mismo tiempo, solo un subproceso puede operar en x para realizar el efecto Como sigue:

50, 100, 150 ... En el programa Python, si desea hacer que el objeto variable sea seguro en un entorno de subprocesos múltiples, puede usar el objeto Lock en subprocesos para resolverlo. El siguiente código demuestra el proceso de bloqueo de la sección crítica.

Importar 

clase de subprocesos ShareCounter: 

    def __init __ (self, initial_value = 0): 
        self._value = initial_value 
        self._value_lock = threading.Lock () 

    def incr (self, delta = 1): 
        with self._value_lock: 
            self._value + = delta 

    def decr (self, delta = 1): 
        con self._value_lock: 
            self._value - = delta 

def test (c): 
    para n en rango (10000): 
        c.incr () 

    para n en rango (10000): 
        c. decr () 

if __name__ == '__main__': 
    c = ShareCounter () 
    t1 = threading.Thread (target = test, args = (c,)) 
    t2 = threading.Thread (target = test, args = (c,)) 
    t3 = threading.Tread (target = test, args = (c,))
 
    t1.start () 
    t2.start () 
    t3.start () 
    print ('Prueba de ejecución') 
    t1.join () 
    t2.join () 
    t3 .join () 
    
    afirmar c._value == 0 
    print ('Locks good!', c._value) # 0

En el código anterior, cuando se usa la instrucción with, el objeto Lock puede garantizar que se produzca un comportamiento mutuamente exclusivo, es decir, solo se ejecuta un subproceso a la vez para ejecutar la instrucción with.

 

Usar objetos de condición

En Python, puede usar el objeto Condición para procesar datos solo después de que se activen ciertos eventos o cuando se cumplan ciertas condiciones. El propósito del objeto Condición es admitir problemas complejos de sincronización de subprocesos.

La condición generalmente se asocia con un bloqueo. Cuando necesite compartir un bloqueo en varias condiciones, puede pasar una instancia de Lock / RLock, de lo contrario, generará automáticamente un bloqueo. El siguiente código usará

Conditon implementa un juego de escondite: 1. Cuando comienza el juego, Seeker primero se cubre los ojos para gobernar a Hider, 2. Después de que Hider recibe la notificación, se esconde y luego notifica a Seeker que puede encontrarla.

importación de subprocesos, 

clase de tiempo Hider (threading.Thread): 
    def __init __ (self, cond, name): 
        super (Hider, self) .__ init __ () # Es necesario ejecutar primero la función de inicialización de la clase padre, de lo contrario el nombre se sobrescribirá por 
        self.cond = cond 
        self.name = name 

    def run (self): 
        time.sleep (1) # Asegúrese de que Seeker primero ejecute 
        self.cond.acquire () # 3, obtenga el bloqueo, realice la siguiente operación 
        print ("He cerrado los ojos ¡Eso es todo! ") 
        Self.cond.notify () # Notificar a otro para desbloquear y suspender 
        self.cond.wait () 

        print (self.name,": Te he encontrado ") 
        self.cond.notify () 
        self .cond.release () 

        print ( self.name , ': I won') 


class Seeker (threading.Thread): 
    def __init __ (self, cond, name): 
        super (Seeker, self) .__ init __ () # Necesita ejecutar primero la función de inicialización de la clase padre, de lo contrario el nombre será Estar cubierto
        self.cond = cond 
        self.name = name 

    def run (self): 
        self.cond.acquire () # 1, obtenga el bloqueo 
        self.cond.wait () # 2, libere la ocupación del bloqueo, mientras el hilo se cuelga, sepa notificar () Y 
        vuelva a ocupar la impresión de bloqueo (self.name, ": lo he ocultado, búscame rápidamente") 
        self.cond.notify () 

        self.cond.wait () 
        self.cond.release () 
        print (self.name, ": Encontrado por usted, hey") 

cond = threading.Condition () 
seeker = Seeker (cond, 'seeker') 
hider = Hider (cond, 'hider') 
seeker.start () 
hider.start () 

"" "¡ 
He cerrado los ojos! 
Buscador: lo he escondido, encuéntrame rápidamente 
oculto: te he encontrado Buscador: te he encontradoHe encontrado a tu 
oculto: gané
buscador: Encontrado por usted, oye "" "

 

Usar objetos de semáforo y semáforo limitado

En Python, puede usar Semaphore y BoundedSemaphore para controlar el contador en un sistema de señal multiproceso.

1. Semáforo: subprocesos de clase. El semáforo es un semáforo que controla el acceso a recursos públicos o secciones críticas. El semáforo mantiene un contador que especifica el número de subprocesos que pueden acceder simultáneamente a los recursos o ingresar a la sección crítica, cada vez

Un hilo recibe la señal, el contador es -1, si el contador es 0, otros hilos dejan de acceder.

importación de subprocesos, 

diversión de def. de tiempo (semáforo, num): 
    semaphore.acquire () 
    print ("降龙十八掌 , 发出% d 掌"% num) 
    time.sleep (3) 
    semaphore.release () 

if __name__ == ' __main__ ': 
    semaphore = threading.Semaphore (2) 

    para num in range (4): 
        t = threading.Thread (target = fun, args = (semaphore, num)) 
        t.start ()  

Después de la ejecución, los subprocesos 0 y 1 se ejecutan al mismo tiempo, y 2, 3 se ejecutan después de 3 segundos.

2. BoundedSemaphore: verificará el valor del contador interno y se asegurará de que no sea mayor que el valor inicial. Si lo excede, se generará un ValueError, que a menudo se utiliza para proteger el acceso restringido a los recursos.

 

Usar objeto de evento

En Python, un objeto de evento es uno de los mecanismos de comunicación más simples entre hilos, un hilo puede activar otros hilos que esperan en un objeto de evento. La clase de implementación del objeto Event es threading.

Esta es una clase que implementa un objeto de evento. Un evento gestiona un indicador. El indicador se puede establecer en verdadero por el método set () o restablecer en falso por el método clear (). El método wait () bloquea hasta que el indicador sea verdadero.

El valor inicial es falso.

importación de subprocesos, 

evento de tiempo = subprocesamiento. Evento () 

def func (): 
    # 
    print ("% s wait for event ..."% threading.currentThread (). getName ()) 

    # event.wait (timeout) 阻塞 线程 ,直到 evento 对象 内部 标 实 位 为 Verdadero , 或 超时
    event.wait () 
    print ("% s recv event".% Threading.currentThread (). GetName ()) 


t1 = threading.Thread (target = func) 
t2 = threading .Thread (target = func) 

t1.start () 
t2.start () 
time.sleep (2) 
print ("MainTread set event") 
event.set () # 将 标识 位 改为 True 


"" " 
Thread-1 wait para evento ... 
Thread-2 espera para evento ... 
MainTread establece evento 
Thread-2 recv event. 
Thread-1 recv event. "" "

  

Usar objeto de temporizador

Temporizador: Temporizador, utilizado para llamar a un método después de un tiempo específico, la acción de temporizador correspondiente puede cancelarse mediante la función cancel ().

import threading 
def func (): 
    print ("ping") 

timer = threading.Timer (5, func) 
timer.start ()

 

Supongo que te gusta

Origin www.cnblogs.com/double-W/p/12685267.html
Recomendado
Clasificación