DEV Community

michael-2509
michael-2509

Posted on

Print in Order

Challenge
Suppose we have a class:

public class Foo {
  public void first() { print("first"); }
  public void second() { print("second"); }
  public void third() { print("third"); }
}
Enter fullscreen mode Exit fullscreen mode

The same instance of Foo will be passed to three different threads. Thread A will call first(), thread B will call second(), and thread C will call third(). Design a mechanism and modify the program to ensure that second() is executed after first(), and third() is executed after second().

Note:

We do not know how the threads will be scheduled in the operating system, even though the numbers in the input seem to imply the ordering. The input format you see is mainly to ensure our tests' comprehensiveness.

Let's Understand the challenge

What an Instance and a Thread?
An object is an instance of a class. In the example below, phone is a class while instance of phone is phone_one. Therefore to create an instance of foo would be to create an object.

class Phone:
    def __init__(self):
        self.brand = "samsung"
        self.model = "A50 
        self.color = "blue"

#object 
phone_one = Phone()
Enter fullscreen mode Exit fullscreen mode

A thread is a set of operations that would be operated at different time sequence. It allow's one perform different actions at different time sequence instead of the order of execution.
let's say you have to wait for an input to complete action one, you can move to the next available action, action two while you await action one.

import threading
import time

def eat(food):
    print("preparing to eat",food)
    time.sleep(1)
    print("back to eating ",food)

def movie(movie):
    print("watching", movie)
    print("Done watching")


x = threading.Thread(target=eat, args=("rice",))
x.start()

y = threading.Thread(target=movie, args=("spiderman",))
y.start()

Enter fullscreen mode Exit fullscreen mode

what you expected as output

preparing to eat rice
back to eating  rice
watching spiderman
Done watching

Enter fullscreen mode Exit fullscreen mode

Actual output

preparing to eat rice
watching spiderman
Done watching
back to eating  rice
Enter fullscreen mode Exit fullscreen mode

If you observe the flow while running eat function, we out of the eat function to the movie function before the final execution of eat and this is because we encoutered a delay in eat function

So to solve this challenge i used a lock object that thread provides. when we have two or more threads access a shared piece of data is called race condition. which is the case in this challenge. Having the same instance of foo pass to the three different threads.

To solve a race condition, a common method is to used the Lock object that thread provides. Lock allows one thread to run at a time until the lock is released before next thread runs

import threading
from threading import Lock

class Number:
    def __init__(self):
        self.lock_one = threading.Lock()
        self.lock_two = threading.Lock()
        self.lock_one.acquire()
        self.lock_two.acquire()

    def first(self, num) -> None:
        print("one", num)
        self.lock_one.release()


    def second(self, num) -> None:
        self.lock_one.acquire()
        print("two", num)
        self.lock_two.release()


    def third(self,num) -> None:
        self.lock_two.acquire()
        print("three", num)

  #object      
num_instance = Number()

thread_a = threading.Thread(target=num_instance.third, args=(1,))
thread_a.start()

thread_b = threading.Thread(target=num_instance.second, args=(2,))
thread_b.start()

thread_c = threading.Thread(target=num_instance.first, args=(3,))
thread_c.start()

Enter fullscreen mode Exit fullscreen mode

OUTPUT

one 3
two 2
three 1
Enter fullscreen mode Exit fullscreen mode

BONUS

Top comments (0)