Exemple de compartició de recursos

Aquí disposeu d’un conjunt d’exemples que comparteixen la pantalla. Es tracta de mostrar per pantalla un llista de 10 línies d’un string donat. En algunes proves s’intercalaran les línies de diversos llistats trencant la unitat del llistatobjectiu. Estudieu els exemples, proveu-los, i expliqueu-vos els resultats obstinguts.

Concurrència de programes des de bash

Fitxer imprimir.py

#!/usr/bin/env python3
import sys

def imprimir(num):
    for i in range(10):
        print(num)
    print(40*'-')

if __name__ == '__main__':
    imprimir(sys.argv[1])

Guió bash execució programes. Fitxer guió imprimir.sh i text executable imprimir [1]:

./imprimir zero  & ./imprimir u  & ./imprimir dos  & ./imprimir tres  & ./imprimir quatre 

Impressió per cada fil d’execució sense tenir en compte zona crítica (compartició pantalla).

Fitxer imprsl.py


import threading
from queue import Queue
import time

def imprimir(num):
    for i in range(10):
        print(num)
    print(40*'-')

if __name__ == '__main__':
    d = {0: 'zero', 1: 'u', 2: 'dos', 3: 'tres', 4: 'quatre', 5: 'cinc'}
    for i in range(5):
        si = d[i]
        t = threading.Thread(target=imprimir, args=(si,))
        t.start()

Impressió per cada fil d’execució tenint en compte zona crítica (compartició pantalla).

Versió 1 (acquire/release)

Fitxer impral2.py


import threading
from queue import Queue
import time

impressio = threading.Lock()

def imprimir(num):
    impressio.acquire()
    for i in range(10):
        print(num)
    print(40*'-')
    impressio.release()

            
if __name__ == '__main__':
    d = {0: 'zero', 1: 'u', 2: 'dos', 3: 'tres', 4: 'quatre', 5: 'cinc'}
    for i in range(5):
        t = threading.Thread(target=imprimir, args=(d[i],))
        t.start()

Versió 2 (with)

Fitxer impral.py


import threading
from queue import Queue
import time

impressio = threading.Lock()

def imprimir(num):
    with impressio:
        for i in range(10):
            print(num)
        print(40*'-')

            
if __name__ == '__main__':
    d = {0: 'zero', 1: 'u', 2: 'dos', 3: 'tres', 4: 'quatre', 5: 'cinc'}
    for i in range(5):
        t = threading.Thread(target=imprimir, args=(d[i],))
        t.start()

Comunicació fils mitjançant cua compartida.

Fitxer cuaImpr.py

import threading
from queue import Queue
import time


impressio = threading.Lock()

def imprimir(item):
    # quan sortim del sangrat, el bloquejador impressio s'allibera
    with impressio:
        for i in range(10):
            print(item)

def impressor(n):
  while True:
    imprimir(q.get())
    q.task_done()  # Notifiquem que hem acabat amb la dada consumida.
                   # important per .join sincronitzar amb l'acabament
    print(f'------------ Fet per Imprenta {n}')
    time.sleep(1)

q = Queue()


if __name__ == '__main__':
    d = {0: 'zero', 1: 'u', 2: 'dos', 3: 'tres', 4: 'quatre', 5: 'cinc',
         6: 'sis', 7: 'set', 8: 'vuit', 9: 'nou'}
    for m in range(10):
        q.put(m)
    for f in range(5):
        fil = threading.Thread(target = impressor, args=(f,))
        fil.daemon = True  # Fil acabarà si principal acaba.
        fil.start()

    q.join() #esperem fils acabin.