# CS 450; Python Thread list example # version 2014-02-19 3:37 PM # # Slightly tweaked after lecture: Printing more comments, # make/use item now prints item number within run instead of # item_count; number of '>' and '<' signs is the length of the # buffer after making/using item. # # Producer/consumer using condition variables # import random, time from time import sleep from threading import Condition, Thread # Buffer size and condition variables # Note horrible code using lots of global variables # item_count = None item_limit = None cv_item = None cv_hole = None # Item routines # def initialize_items(limit=3): global item_count, item_limit item_count = 0 item_limit = limit def item_available(): global item_count, item_limit return item_count > 0 # Say we made an item. Give producer number, item number # within run, and print as many '>' signs as there will be # items in the buffer. # def make_item(id, run): global item_count print('Producer {} made item {} {}'\ .format(id, run, (item_count+1)*">"), flush=True ) item_count = item_count + 1 def hole_available(): global item_count, item_limit return item_count < item_limit # Say we used an item. Give consumer number, item number # within run, and print as many '<' signs as there will be # items in the buffer. # def use_item(id, run): global item_count print('Consumer {} used item {} {}'\ .format(id, run, (item_count-1)*"<"), flush=True ) item_count = item_count - 1 # Produce items # def producer(id, repeat=5, pause=0.25): global cv_item, cv_hole for run in range(repeat): sleep(random.uniform(0, pause)) with cv_hole: while not hole_available(): cv_hole.wait() # Other producers will block at with cv_hole make_item(id, run) with cv_item: cv_item.notify() print('Producer {} done'.format(id)) # Consume items # def consumer(id, repeat=5, pause=8): global cv_item, cv_hole for run in range(repeat): sleep(random.uniform(0, pause)) with cv_item: while not item_available(): cv_item.wait() # Other consumers will block at with cv_item use_item(id, run) with cv_hole: cv_hole.notify() print('Consumer {} done'.format(id)) def main(producers=2, consumers=2, \ prod_pause=0.1, con_pause= 0.15, repeat=10, limit=10 ): global cv_item, cv_hole initialize_items(limit) cv_item = Condition() cv_hole = Condition() if producers > consumers and producers * repeat > limit: print("More producers than consumers: The producers might not finish") elif consumers > producers: print("More consumers than producers: The consumers won't finish") print('Note: code now prints item number within run, not item count') producers = [Thread(target=producer, args=(i,repeat,prod_pause)) \ for i in range(producers) ] consumers = [Thread(target=consumer, args=(i,repeat,con_pause)) \ for i in range(consumers) ] [p.start() for p in producers] [c.start() for c in consumers] [p.join() for p in producers] [c.join() for c in consumers]