Exercise 10: Concurrency and Threading demonstration in Python
1. Find definitions for eight terms and concepts used in threaded programming:
-Thread Synchronisation :
It is a method for preventing deadlock to occur when two or more threads trying to aquire the same resources at the same time by making the thread wait in the line while other thread is accessing the resources or making any change to it, preventing any collision between the them.
-Locks
A lock is a synchronization mechanism for enforcing limits on access to a resource in an environment where there are many threads of execution. Locks are one way of enforcing concurrency control policies.
-DeadLock
A Deadlock is a state in a computer system where two or more process are waiting for each other to finish thier task so that they can use the resource other process is using, but no one does finish the task. Therefore niether of the task can be completed and the resources are occupied as well.
-Semaphores
A semaphore is a protected variable or abstract data type that constiture a classic method of controlling access by several processes to a common resource in a parallel programming environment.
-Mutex (Mututal Exclusion)
It is an algorithm used in concurrent programming to avoid the simultaneous use of a common resource, such as a global variable, by pieces of computer code called critical sections.
-Thread
A thread results from a fork of a computer program into two or more concurrently running tasks. Multiple threads can exists within the same process and share resources such as memory, while different processes do not share these resources.
-Event
It is an action that is usually initiated outside the scope of a program and that is handled by a piece of code inside the program. Events are handled synchronous with the program flow. Main source of events are user who presses a key in the keyboard and hardware devices such as a timer.
-Waitable timer
A waitable time object is a synchronization object whose state is to signaled when the specified due time arrives. Manual-reset and synchronization are two types of waitable timer.
A simple demonstration of the threading module in Python (threaddemo.py) that uses both a lock and semaphore to control concurrency is by Ted Herman at the University of Iowa.The code and sample output below are worth a look.Report your findings.
threaddemo.py
# Create a bunch of threads, let each do some work, wait until all are done
import random
import threading
import time
# This takes about n/3 seconds to run (about n/3 clumps of tasks, times
# about 1 second per clump).
numtasks = 10
# no more than 3 of the 10 can run at once
# create a semaphore bounded up to 3
sema = threading.BoundedSemaphore(value=3)
# create a Read Lock
mutex = threading.RLock()
# running is a global variable to keep track
# of how many threads are running
running = 0
# the TestThread class is a subclass of threading.Thread,
# so it should supply the standard methods: run, ...
class TestThread(threading.Thread):
def run(self):
# tell python we access the global variable
global running
# introduce a random delay between 0 and 2
delay = random.random() * 2
print 'task', self.getName(), 'will run for', delay, 'sec'
# first, wait on the semaphore (limited to three threads)
sema.acquire()
# but only one of these three at a time should update
# the running variable
mutex.acquire()
running = running + 1
print running, 'tasks are running'
# release lock so another can update "running"
mutex.release()
# now sleep for a while (yawn....zzzzzzz)
time.sleep(delay)
# after wakeup, say we are done
print 'task', self.getName(), 'done'
# time to decrement "running"
mutex.acquire()
running = running - 1
print self.getName(), 'is finished.', running, 'tasks are running'
mutex.release()
# and finally, exit the group of three tasks
sema.release()
# main program:build and start all the threads
threads = []
# done in a function just for convenience
def starttasks():
for i in range(numtasks):
# show off Python's formatting feature
# by building a name for each thread
t = TestThread(name=""%i)
# add new name to list
threads.append(t)
# start thread
t.start()
starttasks()
print 'waiting for all tasks to complete'
# next statement waits for all threads to finish
for t in threads: t.join()
print 'all tasks done'
Here is the output window when you run the threaddemo.py script:
PythonWin 2.3.2 (#49, Nov 13 2003, 10:34:54) [MSC v.1200 32 bit (Intel)] on win32.Portions Copyright 1994-2001 Mark Hammond (mhammond@skippinet.com.au) - see
'Help/About PythonWin' for further copyright information.
>>> task will run for 0.120358615571 sec
1 tasks are running
task will run for 0.763990116379 sec
2 tasks are running
task will run for 0.207353153515 sec
3 tasks are running
task will run for 1.55806365714 sec
task will run for 0.776083733579 sec
task will run for 0.336440216469 sec
task will run for 1.55779500185 sec
task will run for 1.96896800957 sec
task will run for 1.57596561512 sec
task will run for 0.634052702735 sec
waiting for all tasks to complete
task done
is finished. 2 tasks are running
3 tasks are running
task done
is finished. 2 tasks are running
3 tasks are running
task done
is finished. 2 tasks are running
3 tasks are running
task done
is finished. 2 tasks are running
3 tasks are running
task done
is finished. 2 tasks are running
3 tasks are running
task done
is finished. 2 tasks are running
3 tasks are running
task done
is finished. 2 tasks are running
3 tasks are running
task done
is finished. 2 tasks are running
task done
is finished. 1 tasks are running
task done
is finished. 0 tasks are running
all tasks done
Here are the findings:
Here is my finding in A simple demonstration of the threading module:
Thread ID is only limited 10 ie form 0 to 9.
Variable delay that is used to control the processing time of thread (2 secs)
Variable sema is a threading semaphore and it is predefined running maximum 3 threads each time (sema = threading.BoundedSemaphore(value=3)).
Variable mutex is used to create the read lock for the thread (mutex = threading.RLock()).
Method acquire(), reads a wait flag(optional).This can be use to avoid blocking if the lock is held by someone else.
Variable running is used to count the total number of running threads.
when TestThread() gets executed, console will print out a thread ID and the expected running time. Then sema.acquire() checks the thread number whether is over 3 or not, if false, mutex creates a read lock for the waiting thread, and adds 1 to running.
When one of the 3 threads get fully executed , mutex releases the read lock of for that very thread and subtracts running by one.Then prints out that the task had been completed. No the one of the threading will be lock to be executed. These process continues for 10 circles or cycles.
No comments:
Post a Comment