Python中的同步原语--锁
from atexit import register
from random import randrange
from threading import Thread, Lock, current_thread
from time import ctime, sleep
class CleanOutputSet(set):
def __str__(self):
return ', '.join(x for x in self)
lock = Lock()
loops = (randrange(2, 5) for x in range(randrange(3, 7)))
remaining = CleanOutputSet()
def loop(nsec):
myname = current_thread().name
lock.acquire()
remaining.add(myname)
print('{} started {}'.format(ctime(), myname))
lock.release()
sleep(nsec)
lock.acquire()
remaining.remove(myname)
print('{} Completed {} ({} secs)'.format(ctime(), myname, nsec))
print(' (remaining: {})'.format(remaining or None))
lock.release()
def main():
print('starting at:', ctime())
for pause in loops:
Thread(target=loop, args=(pause,)).start()
@register
def _atexit():
print('all done at:', ctime())
if __name__ == '__main__':
main()
优化版使用上下文管理器:
...
def loop(nsec):
myname = current_thread().name
with lock:
remaining.add(myname)
print('{} started {}'.format(ctime(), myname))
sleep(nsec)
with lock:
remaining.remove(myname)
print('{} Completed {} ({} secs)'.format(ctime(), myname, nsec))
print(' (remaining: {})'.format(remaining or None))
...
Python中的同步原语--信号量
from atexit import register
from random import randrange
from threading import BoundedSemaphore, Lock, Thread
from time import ctime, sleep
lock = Lock()
MAX = 5
candytray = BoundedSemaphore(MAX)
def refill():
with lock:
print('Refilling candy...')
try:
candytray.release()
except ValueError:
print('full, skipping')
else:
print('ok')
def buy():
with lock:
print('Buying candy...')
if candytray.acquire(False):
print('OK')
else:
print('empty, skipping')
def producer(loops):
for x in range(loops):
refill()
sleep(randrange(3))
def consumer(loops):
for x in range(loops):
buy()
sleep(randrange(3))
def _main():
print('starting at:{}'.format(ctime()))
nloops = randrange(2, 6)
print('THE CANDY MACHINE (full with {} bars)!'.format(MAX))
Thread(target=consumer, args=(randrange(nloops, nloops+MAX+2),)).start()
Thread(target=producer, args=(randrange(nloops, nloops+MAX+2),)).start()
@register
def _atexit():
print('all DONE at:', ctime())
if __name__ == '__main__':
_main()