RosettaCodeData/Task/Atomic-updates/Python/atomic-updates.py

75 lines
1.9 KiB
Python

from __future__ import with_statement # required for Python 2.5
import threading
import random
import time
terminate = threading.Event()
class Buckets:
def __init__(self, nbuckets):
self.nbuckets = nbuckets
self.values = [random.randrange(10) for i in range(nbuckets)]
self.lock = threading.Lock()
def __getitem__(self, i):
return self.values[i]
def transfer(self, src, dst, amount):
with self.lock:
amount = min(amount, self.values[src])
self.values[src] -= amount
self.values[dst] += amount
def snapshot(self):
# copy of the current state (synchronized)
with self.lock:
return self.values[:]
def randomize(buckets):
nbuckets = buckets.nbuckets
while not terminate.isSet():
src = random.randrange(nbuckets)
dst = random.randrange(nbuckets)
if dst!=src:
amount = random.randrange(20)
buckets.transfer(src, dst, amount)
def equalize(buckets):
nbuckets = buckets.nbuckets
while not terminate.isSet():
src = random.randrange(nbuckets)
dst = random.randrange(nbuckets)
if dst!=src:
amount = (buckets[src] - buckets[dst]) // 2
if amount>=0: buckets.transfer(src, dst, amount)
else: buckets.transfer(dst, src, -amount)
def print_state(buckets):
snapshot = buckets.snapshot()
for value in snapshot:
print '%2d' % value,
print '=', sum(snapshot)
# create 15 buckets
buckets = Buckets(15)
# the randomize thread
t1 = threading.Thread(target=randomize, args=[buckets])
t1.start()
# the equalize thread
t2 = threading.Thread(target=equalize, args=[buckets])
t2.start()
# main thread, display
try:
while True:
print_state(buckets)
time.sleep(1)
except KeyboardInterrupt: # ^C to finish
terminate.set()
# wait until all worker threads finish
t1.join()
t2.join()