Tuesday 5 January 2021

Why do locally-started threads not terminate at the end of each iteration?

According to what is suggested in the answer here, to get rid of RuntimeError: threads can only be started once , I have tried to start each thread when its corresponding object is created (instead of directly starting them in the main body of the code). The final purpose is that when each iteration of the main code is finished, the threads which are running in it also terminate. To start all threads simultaneously, I consider

for obj in objects:
    obj.launch_obj(q)

in the following snippet.

import random
from threading import Thread
from queue import Queue

objects = []
threads = []

def generate_id():
    My_class.ID +=1
    return My_class.ID

def reset_id():
    My_class.ID = 0

class My_class(object):

    ID = 0

    def __init__(self):
        self.id = generate_id()
        objects.append(self)

    def launch_obj(self, q):
        thread = Thread(target=do, args=(q,self.id,))
        threads.append(thread)
        thread.start()

epochs = 4

success = [0 for x in range(epochs)]

def do(q, id):
    temp = q.get()
    if random.random() > 0.5:
        temp += 1
    print("\t object: {0} -> temp: {1}".format(id, temp))
    return q.put(temp)

for epoch in range(epochs):
    print("iteration: {0}".format(epoch+1))
    temp = 0
    q = Queue()
    q.put(temp)
    obj1 = My_class()
    obj2 = My_class()

    for obj in objects:
        obj.launch_obj(q)

    for thread in threads:
        thread.join()

    temp = q.get(temp)

    success[epoch] = temp

    reset_id()

However, The output reads like

iteration: 1
     object: 1 -> temp: 0
     object: 2 -> temp: 0
iteration: 2
     object: 1 -> temp: 0
     object: 2 -> temp: 0
     object: 1 -> temp: 1
     object: 2 -> temp: 2
iteration: 3
     object: 1 -> temp: 0
     object: 2 -> temp: 1
     object: 1 -> temp: 2
     object: 2 -> temp: 3
     object: 1 -> temp: 3
     object: 2 -> temp: 3
iteration: 4
     object: 1 -> temp: 0
     object: 2 -> temp: 1
     object: 1 -> temp: 1
     object: 2 -> temp: 2
     object: 1 -> temp: 3
     object: 2 -> temp: 4
     object: 1 -> temp: 4
     object: 2 -> temp: 4

in which the threads of each iteration are not killed at the end of that iteration. On the other hand, if I start the threads individually, like

obj1.launch_obj(q)
obj2.launch_obj(q)

then, the output's form apparently becomes similar to what I expect.

iteration: 1
     object: 1 -> temp: 0
     object: 2 -> temp: 1
iteration: 2
     object: 1 -> temp: 1
     object: 2 -> temp: 1
iteration: 3
     object: 1 -> temp: 1
     object: 2 -> temp: 1
iteration: 4
     object: 1 -> temp: 1
     object: 2 -> temp: 1

So, I have the following two related questions.

1- What is the difference between starting threads in a loop vs. doing it sequentially?

2- How may one fix the behavior of the first snippet (in which threads are started in a loop) such that the threads of each iteration are terminated at the end of that iteration?

Thanks



from Why do locally-started threads not terminate at the end of each iteration?

No comments:

Post a Comment