0

Why the output is coming differently on idle and online editor , for the given threading example. Please help in understanding the actual issue which is causing this?

import threading
from time import sleep, time, ctime

loops = [4, 2]

def loop(nloop, nsec):
    print('start loop', nloop, 'at:', ctime(time()))
    sleep(nsec)
    print('loop', nloop, 'done at:', ctime(time()))

def main():
    print('starting threads…')
    
    threads = []
    nloops = range(len(loops))
    
    for i in nloops:
        t = threading.Thread(target=loop,
        args=(i, loops[i]))
        threads.append(t)
    
    for i in nloops: # start threads
        threads[i].start()
        
    for i in nloops: # wait for all
        threads[i].join() # threads to finish)
    
    print('all DONE at:', ctime(time()))


if __name__ == '__main__':
    main()

Expected output

starting threads…    
start loop 0 at: Fri Sep 17 12:43:26 2021  
start loop 1 at: Fri Sep 17 12:43:26 2021  
loop 1 done at: Fri Sep 17 12:43:28 2021  
loop 0 done at: Fri Sep 17 12:43:30 2021  
all DONE at: Fri Sep 17 12:43:30 2021 

Output coming on idle on my local machine

starting threads…  
start loopstart loop  01  at:at:  Fri Sep 17 18:19:39 2021Fri Sep 17 18:19:39 2021  

loop 1 done at: Fri Sep 17 18:19:42 2021  
loop 0 done at: Fri Sep 17 18:19:44 2021  
all DONE at: Fri Sep 17 18:19:44 2021  
ForceBru
  • 43,482
  • 10
  • 63
  • 98
  • 1
    I don't see any issues: the threads are started almost simultaneously, are run _almost_ in parallel, and thus partially overwrite each other's output – ForceBru Sep 17 '21 at 13:18
  • But , on one platform the output , is other , and on other it is different , a beginner , on this thing is sure to be confused , how can we comprehend this – Vaibhav Yadav Sep 17 '21 at 13:23
  • 1
    I read somewhere that once you start reasoning about the order in which threads are run, you're doomed to fail, no matter how skilled or knowledgeable you are, because this stuff is almost random, and thread synchronisation is a separate difficult issue. I think there's not much to comprehend: you can treat the order in which threads execute code as non-deterministic and be sure not to rely on this order at all. If you absolutely need thread synchronisation, Python provides mutexes and locks. – ForceBru Sep 17 '21 at 13:30
  • sir , like in the above situation , i tried to understand your answer , but sir , if we have to output something like in above case , and suppose it will be shown to the user , then how can we avoid relying on the order in which this output will be shown to user – Vaibhav Yadav Sep 17 '21 at 13:43
  • @VaibhavYadav I'm not sure I understand your question but if you want to avoid overwriting your output, put a lock around your `print`. https://stackoverflow.com/a/3311157/12479639 – Axe319 Sep 17 '21 at 13:55
  • 1
    "how can we avoid relying on the order in which this output will be shown to user" - well, you're already not relying on any order. Hence, the order is unpredictable and you can get messy output as shown in your post, which is normal. If, on the contrary, you want to _force_ some order, you can use `threading.Lock` like shown here: https://stackoverflow.com/questions/10525185/python-threading-how-do-i-lock-a-thread – ForceBru Sep 17 '21 at 13:56
  • so ,is there any uses of this multithreading without using locks and mutexes , i do not know exactly , but i simply want to know , that , is the output without locks , is always underterministic , and if it is , then what are the use cases for multithreading without using locks and all – Vaibhav Yadav Sep 17 '21 at 13:58
  • so , if we force order , does it not cause the whole idea behind threading to suffer , which is to save time , when a particular task is taking more time , instead of waiting , move ahead , but if we do locking , then eitherway , we are waiting for a praticular thread to be finished , and then continue the below execution. – Vaibhav Yadav Sep 17 '21 at 14:03
  • One use case are web servers that serve thousands of clients simultaneously, for example. If you extend this to "true" multithreading that can use multiple CPU cores (which is not the case in Python), this opens up possibilities for fast parallel data processing. If you extend this even further, GPUs (the things that render graphics on your screen) are massively parallel and can process multiple pixels at the same time, – ForceBru Sep 17 '21 at 14:04
  • Yes, locking means making other threads wait, so if you're using locks excessively, this can easily undermine the idea of parallel computing and make things essentially sequential. – ForceBru Sep 17 '21 at 14:05
  • ok , thanks a lot , now i got a little understanding of this – Vaibhav Yadav Sep 17 '21 at 14:06
  • Just to add onto this, `threading` is not a tool to throw at every (even most) problems. When you reach a problem that `threading` is needed to solve, like processing large amounts of IO, you'll probably know it. – Axe319 Sep 17 '21 at 14:08

1 Answers1

0

If the order in which threads were started is important when acquiring their results, then one way to manage this is to pass an incrementing id to each thread. Each thread should return its results to some thread-safe location (e.g. a list). Then, when all the threads have terminated, you just need to sort the list keyed on its id. Here's an example:-

from threading import Thread
import random

results = []

def myThread(id):
    results.append((id, random.randint(0, 100)))

def main():
    threads = []

    for id in range(10):
        t = Thread(target=myThread, args=(id,))
        t.start()
        threads.append(t)

    for t in threads:
        t.join()
    
    print(sorted(results, key=lambda x: x[0]))

if __name__ == '__main__':
    main()