1

I want to run two functions in parallel which print two lists in parallel. But what I get is one list, being printed after the other list has completed.

I have tried the following code.

import threading
import time

def fun1():
    testz=['z','y','x','w','v','u','t']
    for j in testz:
        print (j)
        time.sleep(1)

def fun2():
    test=['a','b','c','d','e','f','g']
    for i in test:
        print (i)
        time.sleep(1)


thread1 = threading.Thread(target=fun1())
thread2 = threading.Thread(target=fun2())

thread1.start()
time.sleep(0.5)
thread2.start()

thread1.join()
thread2.join()

The result that I expect for this is :

z
a
y
b
x
c
w
d
v
e
u
f
t
g

but what I get is :

z
y
x
w
v
u
t
a
b
c
d
e
f
g

which seems like the two threads are being run one after the other.

0

6 Answers 6

4

The problem is that you run the functions in the main thread, not in a subthread. You call the functions first, before giving the returned valued as thread target. Your code should be:

thread1 = threading.Thread(target=fun1)
thread2 = threading.Thread(target=fun2)

Then you will get the expected result.

Sign up to request clarification or add additional context in comments.

3 Comments

Would you mind to explain in some explicit manner, what did you try to say?
@user3666197: this is not a pertinent discussion here. The question was asked by a novice, who is more than likely not interested in your point. Multi-threading in Python is very useful in many situations. In other situations, multi-processing is a better solution. Both are well supported in Python. The GIL is there for a very good reason, but if it causes performance problems, multi-processing is easy to implement in Python as it has the same API as multi-threading.
Not a fair nor a correct again. No need to explain the design-rationale for GIL for concurrent-access-avoidance(by a must to enter into monopolistic ownership state ~ enforced re-[SERIAL]-isation),yet very important is to present the real add-on costs of using GIL-orchestrated multi-threading.The {disk|network}-I/O-latency-masking is the only "economically"-fair use-case for python GIL-locked threading. All other use-cases are prone to yield slowdown <= 1instead of speedup and benchmarking ( or low-level architecture aware designs ) will answer the lump sum of the add-on costs.
1

If you run the your code in interactive mode, you will get the following output

>>> import threading
>>> import time
>>> 
>>> def fun1():
...     testz=['z','y','x','w','v','u','t']
...     for j in testz:
...         print (j)
...         time.sleep(1)
... 
>>> def fun2():
...     test=['a','b','c','d','e','f','g']
...     for i in test:
...         print (i)
...         time.sleep(1)
... 
>>> 
>>> thread1 = threading.Thread(target=fun1())
z
y
x
w
v
u
t
>>> thread2 = threading.Thread(target=fun2())
a
b
c
d
e
f
g
>>> 
>>> thread1.start()
>>> time.sleep(0.5)
>>> thread2.start()
>>> 
>>> thread1.join()
>>> thread2.join()

You can see that as soon as you create a thread for fun1() with thread1 = threading.Thread(target=fun1()), fun1() is executed.
Similarly as soon as the thread is created for fun2() it is executed.
Thus both the functions are not actually running parallelly and you are getting that output.

Comments

1

At creation of your threads you pass the result of fun1 / fun2 as target instead of the function itself. This is the reason why the functions are executed instantly instead, and not just after you start the thread.

Try to replace your thread-creation with

thread1 = threading.Thread(target=fun1)
thread2 = threading.Thread(target=fun2)

Comments

1

Problem with your code was:

thread1 = threading.Thread(target=fun1())
thread2 = threading.Thread(target=fun2())

Here, it was called function as whole in main thread itself. That is, both function are being called with same threadID

<_MainThread(MainThread, started 4339086784)>
z
y
x
w
v
u
t
<_MainThread(MainThread, started 4339086784)>
a
b
c
d
e
f
g

Proper, syntax for creating threading object should be :

thread1 = threading.Thread(target=fun1)
thread2 = threading.Thread(target=fun2)

After changing : Output

z
a
y
b
x
c
w
d
v
e
u
f
t
g

Comments

0

Threading does not make code run in parallel, it provides the illusion of running code in parallel. This falls under the bigger umbrella of concurrency.

You are creating two threads. A thread is going to do some job, and the OS can shut it down at any point to give resources to another thread. Then stop the other thread, and continue on with the initial one. It will do this seemingly randomly.

Printing elements of these lists occurs so fast, that the thread was never stopped by the OS. Also, be aware that printing with threads can lead to race conditions. Essentially, odd behaviour that can be difficult to debug. Do some fuzzing, basically add a sleep with random numbers for each iteration, sleep(random.random()), and you will see these race conditions come alive.

If you want the literal print output you stated in your question, you can do as follows:

from itertools import chain

for i in chain(*zip(list1, list2)):
    print(i)

1 Comment

there are time.sleep(1)s in the inner loops. printing might be "fast", but these pauses will certainly provide time for the other threads to run. however, as other answers have said, this isn't what the code is actually doing
-1

Your first thread finishes before you start the second since you have a sleep there and also you are executing the functions. You should pass the callable to the thread (passing the function without the ()). You cannot guarantee that your code is going to behave as you expect and give you the same result in each execution.

If you don't need threading you can use a simple zip:

for a, b in zip(list1, list2):
    print(a)
    print(b)

if you really need multithreading and each element of th elist executed in turns you can look at Condition() to lock the threads and use acquire() and release() methods.

1 Comment

my real intention was to do two serial communications parallelly. This was just to clarify whether the way of defining was correct.@EvertW 's answer was what i was looking for. Thanks for your answer too

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.