Producent a konzument
Užitečné odkazy
- Python
threading
— Thread-based parallelism - Python
Condition
— Thread-based parallelism - Zdrojové kódy z cvičení formou notebooku
Objekt Condition
Podmínka je vždy asociována s nějakým druhem zámku. Podmínce může být zámek předán, případně si vytvoří zámek svůj. Již známe metody acquire()
a release()
jsou předány zámku v objektu Condition
.
Novinkou však jsou metody wait()
a notify()
. Metoda wait()
uvolní zámek a čeká dokud jej jiné vlákno nepotvrdí metodou notify()
, nebo notify_all()
a poté zámek zamče.
Metody notify()
a notify_all()
neuvolňují zámek. To znamená, že probuzené vlákno okamžitě nevysoupí ze svého volání wait()
, ale počká až se vlákno které volalo notify()
vzdá vlastnictví zámku.
Condition
je většinou používán následovně:
1
2
3
4
5
6
7
8
9
10
# Consume one item
with cv:
while not an_item_is_available():
cv.wait()
get_an_available_item()
# Produce one item
with cv:
make_an_item_available()
cv.notify()
Producent a konzument
V následující implementaci dochází k problému konzumace prázdné fronty.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
from threading import Thread, Lock
import time
import random
queue = []
lock = Lock()
class ProducerThread(Thread):
def run(self):
# Vytvoreni seznamu [0, 1, 2, 3, 4]
nums = range(5)
# Umozneni zapisu do globalni promenne (append)
global queue
for _ in range(10):
# Vyber nahodneho cisla z [0, 1, 2, 3, 4]
num = random.choice(nums)
with lock:
queue.append(num)
print("Produced {}".format(num))
time.sleep(random.random())
class ConsumerThread(Thread):
def run(self):
# Umozneni zapisu do globalni promenne (pop)
global queue
for _ in range(10):
with lock:
# Demonstrace problemu, pop na prazdnou frontu
# Konzument by mel cekat
if not queue:
print("Nothing in queue, but consumer will try to consume")
num = queue.pop(0)
print("Consumed {}".format(num))
time.sleep(random.random())
ProducerThread().start()
ConsumerThread().start()
Úkol
Předchozí kód upravte za pomoci Condition
tak, aby nedocházelo ke konzumaci prázdné fronty. Pokud ve frontě nebude žádné číslo, konzument musí čekat.
Úkol
Upravte úkol tak aby velikost fronty byla omezena. Například na délku 5 hodnot ve frontě. K řešení využíjte Condition
.