Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
222 views
in Technique[技术] by (71.8m points)

Python multithreading producing funky results

I'm fairly new to multithreading in Python and encountered an issue (likely due to concurrency problems). When I run the code below, it produces "normal" 1,2,3,4,5,6,7,8,9 digits for the first 9 numbers. However, when it moves on to the next batch of numbers (the ones that should be printed by each thread after it "sleeps" for 2 seconds) it spits out:

  • different numbers each time
  • often very large numbers
  • sometimes no numbers at all

I'm guessing this is a concurrency issue where by the time each original thread got to printing the second number after "sleep" the i variable has been tampered with by the code, but can someone please explain what exactly is happening step-by-step and why the no numbers/large numbers phenomenon?

import threading
import time

def foo(text):
    print(text)
    time.sleep(2)
    print(text)

for i in range(1,10):
    allTreads = []
    current_thread = threading.Thread(target = foo, args= (i,))
    allTreads.append(current_thread)
    current_thread.start()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Well, your problem is called race condition. Sometimes when the code is executed, one thread will print a number before the implicit ' ' of another thread, and that's why you often see those kind of behaviours.

Also, whats the purpose of the allTreads list there? It is restarted at every iteration, so it stores the current_thread and then is deleted at the end of the current iteration.

In order to avoid race conditions, you need some kind of synchronization between threads. Consider the threading.Lock(), in order to avoid that more than one thread at a time prints the given text:

import threading
import time


lock = threading.Lock()

def foo(text):
    with lock:
        print(text)
    time.sleep(2)

    with lock:
        print(text)

for i in range(1,10):
    allTreads = []
    current_thread = threading.Thread(target = foo, args= (i,))
    allTreads.append(current_thread)
    current_thread.start()

The threading documentation in python is quite good. I recommend you to read these two links:

Python Threading Documentation

Real Python Threading


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...