Reputation: 3
from threading import Thread
from multiprocessing import Process
import time
def f(name):
print(name)
if __name__ == '__main__':
for _ in range(10):
t1 = Thread(target=f, args=['first'])
t2 = Thread(target=f, args=['second'])
t1.start()
t2.start()
t1.join()
t2.join()
print()
in most cases I get:
first
second
and sometimes
firstsecond
If I add time.sleep(0.01)
to the function:
def f(name):
time.sleep(0.01)
print(name)
in most cases I get something like:
firstsecond
secondfirst
t1 = Process(target=f, args=['first'])
t2 = Process(target=f, args=['second'])
I get only
first
second
time.sleep(0.01)
affect the result in first case?Upvotes: 0
Views: 175
Reputation: 40773
The nature of threading is unpredictable. What you experience with print()
is sometimes when a thread is printing, other thread is also print, thus resulting in a messy output.
When dealing with threads, the sure way is to use logging
instead of print
. Here is a modified code that you have:
import logging
from threading import Thread
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s | %(levelname)-8s | thread: %(threadName)-24s | %(message)s",
)
def f(name):
logging.debug(name)
if __name__ == "__main__":
for _ in range(10):
t1 = Thread(target=f, args=["first"])
t2 = Thread(target=f, args=["second"])
t1.start()
t2.start()
t1.join()
t2.join()
Output:
2024-05-01 16:48:23,271 | DEBUG | thread: Thread-1 (f) | first
2024-05-01 16:48:23,271 | DEBUG | thread: Thread-2 (f) | second
2024-05-01 16:48:23,271 | DEBUG | thread: Thread-3 (f) | first
2024-05-01 16:48:23,271 | DEBUG | thread: Thread-4 (f) | second
2024-05-01 16:48:23,271 | DEBUG | thread: Thread-5 (f) | first
2024-05-01 16:48:23,271 | DEBUG | thread: Thread-6 (f) | second
2024-05-01 16:48:23,271 | DEBUG | thread: Thread-7 (f) | first
2024-05-01 16:48:23,271 | DEBUG | thread: Thread-8 (f) | second
2024-05-01 16:48:23,271 | DEBUG | thread: Thread-9 (f) | first
2024-05-01 16:48:23,271 | DEBUG | thread: Thread-10 (f) | second
2024-05-01 16:48:23,272 | DEBUG | thread: Thread-11 (f) | first
2024-05-01 16:48:23,272 | DEBUG | thread: Thread-12 (f) | second
2024-05-01 16:48:23,272 | DEBUG | thread: Thread-13 (f) | first
2024-05-01 16:48:23,272 | DEBUG | thread: Thread-14 (f) | second
2024-05-01 16:48:23,272 | DEBUG | thread: Thread-15 (f) | first
2024-05-01 16:48:23,272 | DEBUG | thread: Thread-16 (f) | second
2024-05-01 16:48:23,272 | DEBUG | thread: Thread-17 (f) | first
2024-05-01 16:48:23,272 | DEBUG | thread: Thread-18 (f) | second
2024-05-01 16:48:23,272 | DEBUG | thread: Thread-19 (f) | first
2024-05-01 16:48:23,272 | DEBUG | thread: Thread-20 (f) | second
```
Upvotes: 0
Reputation: 27190
How time.sleep()
affects multi-threading is, it makes a blocking system call. That is to say, it waits for something. time.sleep()
waits for the clock. Other blocking system calls wait for things like mouse clicks and key presses or, for network packets or, for a disk drive to return some blocks of data. What they all have in common is, they are yield points. That is to say, they are points where your code voluntarily stops using the CPU, and allows some other thread or process to use it.
None of this explains the output that you are seeing. The only explanation for the output that you are seeing is that all of the different outputs are allowed by multithreading. Basically, you have two threads that concurrently print something. "Concurrently" means that there's no guarantee about the order in which the printouts happen.
Upvotes: 0
Reputation: 13
This is most likely due to the python print buffer. Since you're working with the output stream which is line buffered, it waits until an iteration is completed before manually flushing the buffer to stdout. In fact, it most likely has nothing to do with multiprocessing.
When you call the script, use the -u flag (eg: python3 -u test.py) to disable the print buffer for the whole thing, or use print(name, flush=True)
.
Upvotes: 0