Exemple 1 de compartició de memòria

El fitxer comptador.py crea 10 fils de control que incrementa en 1 la variable compartida n.

La execució de n = n + 1 per incrementar la variable n pot donar problemes si la instrucció es tradueix a llenguatge màquina com vàries instruccions (consultar n i baixar a un registre, incrementar registre, guardar resultat registre en l’indret de n. Si es tradueix com una sola instrucció o no hi ha problema ja que no es pot interrompre una instrucció del processador enmig de la seva execució. Depén també de com actúa el planificador del sistema operatiu. Per provocar el problema s’ha intercalat la suspensió del fil mitjançant sleep “s de manera que el càlcul de l’increment descomposat queda interromput. Podreu observar en diverses execucions de comptador.py que els resultats son incerts.

Amb comptadormutex.py el resultat sempre serà 10 per l’increment individual de cada fil.

Comptador sense pany (lock)

Fitxer comptador.py

from threading import Thread, Lock, Semaphore
from time import sleep
from random import randint

mutex = Lock()
comptador = 0

def fill():
    global comptador
    sleep(0.001*randint(1,5))
    c = comptador
    sleep(0.001*randint(1,5))
    r = c + 1
    comptador = r

if __name__ == '__main__':
    fills=[]
    for i in range(10):
        f = Thread(target=fill, args= ())
        fills.append(f)
        f.start()
    for f in fills:
        f.join()
    print(comptador)

Comptador amb pany (lock)

Fitxer comptadormutex.py

from threading import Thread, Lock, Semaphore
from time import sleep
from random import randint

mutex = Lock()
comptador = 0

def fill():
    global comptador
    mutex.acquire()
    sleep(0.001*randint(1,5))
    c = comptador
    sleep(0.001*randint(1,5))
    r = c + 1
    comptador = r
    mutex.release()

if __name__ == '__main__':
    fills=[]
    for i in range(10):
        f = Thread(target=fill, args= ())
        fills.append(f)
        f.start()
    for f in fills:
        f.join()
    print(comptador)