UNIT 4.
CHAPTER 2 THREADS
Study material for programs explained in video files named as
race_condition,race_condition1 and thread_synchr
Thread Synchronization:
To understand the race condition let us consider one more example. Suppose two railway
reservation clerks from two different places send request for reserving a same seat at the same
time to the server. Two client request are handled by two threads, as two threads act
simultaneously on function that do the reservation, we may get a wrong result such as same seat
is reserved for two person. This is race condition this occurs because two or more thread act on
same function at the same time. To avoid race condition synchronization of thread is needed.
Mean at a time only one thread should act on a method or function.
#pyhton program to illustrate race condition through seat reservation
from threading import *
from time import *
class Railway:
def __init__(self,seats):
self.seats_av=seats
def reserve(self,w):
print("no of seats avialbel",self.seats_av)
if self.seats_av>=w:
name=current_thread().getName()
print("seat is alloted for",name)
self.seats_av-=w
sleep(1)
else:
print("Sorry no seats are avialble")
r=Railway(1)
t1=Thread(target=r.reserve,args=(1,))
t2=Thread(target=r.reserve,args=(1,))
t1.setName("First Person")
t2.setName("Second Person")
t1.start()
t2.start()
output1:
no of seats avialbel 1
seat is alloted for First Person
no of seats avialbel 0
Sorry no seats are avialble
Output2:
no of seats avialbelno of seats avialbel 1
seat is alloted for Second Person
Sorry no seats are avialble
In the above program race condition is occurred. To avoid a race condition threads must be
synchronized. Thread synchronization means when a thread is already acting on object,
preventing any other thread from acting on the same object. Thread synchronization is done
using the following techniques
Using locks
Using semaphores
Thread synchronization using lock:
Locks can be used to lock the object on which the thread is acting. When a thread enters the
object it locks the object and after the execution is completed, it will unlock the object and comes
out of it.
We can create a lock by creating a object of Lock class as
l=Lock()
to lock the current object, we should use acquire() method as
l.acquire()
to unlock or release the object,we can use release() method as
l.release()
#pyhton program to synchronize the threads using lock concept
from threading import *
from time import *
class Railway:
def __init__(self,seats):
self.seats_av=seats
#lock object is created
self.l=Lock()
def reserve(self,w):
#accquire the lock
self.l.acquire()
print("no of seats avialbel",self.seats_av)
if self.seats_av>=w:
name=current_thread().getName()
print("seat is alloted for",name)
self.seats_av-=w
sleep(1)
else:
print("Sorry no seats are avialble")
#release the lock
self.l.release()
r=Railway(1)
t1=Thread(target=r.reserve,args=(1,))
t2=Thread(target=r.reserve,args=(1,))
t1.setName("First Person")
t2.setName("Second Person")
t1.start()
t2.start()
output1:
no of seats avialbel 1
seat is alloted for First Person
no of seats avialbel 0
Sorry no seats are avialble
Output2:
no of seats avialbel 1
seat is alloted for First Person
no of seats avialbel 0
Sorry no seats are avialble
For every execution of the program we will get the same output
Thread synchronization using semaphore:
A semaphore is an object that provides synchronization based on counter. A semaphore is
created as an object of semaphore class as
l=Semaphore(countervalue) #here the counter value by default is 1
if the counter value is not given, the default value of the counter will be 1. When acquire()
method is called, the counter gets decremented by 1 and when release() is called it is
incremented by 1. These methods are used in the following format:
l.acquire() #makes counter 0 and then lock
#code that is locked by semaphore
l.release() # counter is 0 so unlock and make counter 1
#pyhton program to synchronzie the threads using semaphore concept
from threading import *
from time import *
class Railway:
def __init__(self,seats):
self.seats_av=seats
#create a semaphore object
self.l=Semaphore()
def reserve(self,w):
#acquire a lock and counter becomes 0
self.l.acquire()
print("no of seats avialbel",self.seats_av)
if self.seats_av>=w:
name=current_thread().getName()
print("seat is alloted for",name)
self.seats_av-=w
sleep(1)
else:
print("Sorry no seats are avialble")
#release a lock and counter becomes 1
self.l.release()
r=Railway(1)
t1=Thread(target=r.reserve,args=(1,))
t2=Thread(target=r.reserve,args=(1,))
t1.setName("First Person")
t2.setName("Second Person")
t1.start()
t2.start()
output1:
no of seats avialbel 1
seat is alloted for First Person
no of seats avialbel 0
Sorry no seats are avialble
Output2:
no of seats avialbel 1
seat is alloted for First Person
no of seats avialbel 0
Sorry no seats are avialble
We get the same output for each execution of the program