Exemple 2 de compartició de memòria

El fitxer comptadorSZC.py crea 2 fils de control que usen la variable compartida n. Un fil incrementa 10000 vegades la variable n. L’altre fil la decrementa 10000 vegades. Amb el valor inicial 0, el resultat de:py:obj:n al final de l’execució dels fils, n ha de valer 0. Comproveue que això no és així i el resultat és incert.

Amb el fitxer comptadorAZC.py s’ha protegit la operació d’increment o decrement com a zona crítica. El resultat sempre serà zero. Aquí és on es pot veure l’increment o decrement no és atòmic.

Comptador sense pany (lock)

Fitxer comptadorSZC.py

import threading

n=0
nVegades=1000000

def fil1():
    global n
    for i in range(nVegades):
        n = n + 1

def fil2():
    global n
    for i in range(nVegades):
        n = n - 1

def principal():
    t1= threading.Thread(target=fil1)
    t2= threading.Thread(target=fil2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(n)

if __name__=="__main__":
    principal()

Comptador amb pany (lock)

Fitxer comptadorAZC.py

import threading

n=0
nVegades=1000000
critic=threading.Lock()

def fil1():
    global n
    for i in range(nVegades):
        critic.acquire()
        n = n + 1
        critic.release()

def fil2():
    global n
    for i in range(nVegades):
        critic.acquire()
        n = n - 1
        critic.release()

def principal():
    t1= threading.Thread(target=fil1)
    t2= threading.Thread(target=fil2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(n)

if __name__=="__main__":
    principal()

Comptador amb pany (lock) Versió en classes.

Fitxer comptadorCAZC.py

import threading

n=0

class ComptaDescompta(threading.Thread):

    def __init__(self, nVegades, critic, delta):
        super().__init__()
        self.nVegades = nVegades
        self.critic = critic
        self.delta = delta

    def run(self):
        global n
        for i in range(self.nVegades):
            self.critic.acquire()
            n = n + self.delta
            self.critic.release()


def principal():
    nVegades=1000000
    critic=threading.Lock()
    t1= ComptaDescompta(nVegades, critic,  1)
    t2= ComptaDescompta(nVegades, critic, -1)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(n)

if __name__=="__main__":
    principal()