In this next example, we are going to implement our own version of the Dining Philosophers problem in Python using RLocks, which we'll cover later on in this chapter. These Rlocks will represent the forks in our problem. We'll start by defining our Philosopher class and constructor like this:
class Philosopher(threading.Thread):
def __init__(self, leftFork, rightFork):
print("Our Philosopher Has Sat Down At the Table")
threading.Thread.__init__(self)
self.leftFork = leftFork
self.rightFork = rightFork
The Philosopher class, which inherits from the Python's native thread class, takes in both a left and a right fork in its constructor function. It then initializes the thread that we can start later on. After we've defined this, we then have to define our thread's run function as follows:
def run(self):
print("Philosopher: {} has started thinking".format(threading.current_thread()))
while True:
time.sleep(random.randint(1,5))
print("Philosopher {} has finished thinking".format(threading.current_thread()))
self.leftFork.acquire()
time.sleep(random.randint(1,5))
try:
print("Philosopher {} has acquired the left fork".format(threading.current_thread()))
self.rightFork.acquire()
try:
print("Philosopher {} has attained both forks, currently
eating".format(threading.current_thread()))
finally:
self.rightFork.release()
print("Philosopher {} has released the right fork".format(threading.current_thread()))
finally:
self.leftFork.release()
print("Philosopher {} has released the left fork".format(threading.current_thread()))
In this run function, we first think for a random amount of time between 1 and 5 seconds. When our Philosopher finishes thinking, we then attempt to acquire the left fork and again sleep for another 1-5 seconds in order to easily follow the console output.
After we've again finished waiting, we go on to try and acquire the right fork so that we can go into an eating state. We eat only very briefly before releasing both the left and the right fork.