search
HomeBackend DevelopmentPython TutorialAn in-depth understanding of multithreading in Python. A must-read for newbies

Example 1
We are going to request five different URLs:
Single threaded

import time 
import urllib2    
defget_responses():   
urls=[     
‘http://www.baidu.com',     
‘http://www.amazon.com',     
‘http://www.ebay.com',     
‘http://www.alibaba.com',     
‘http://www.jb51.net'  
 ]   
start=time.time()  
forurlinurls:    
printurl    
resp=urllib2.urlopen(url)     
printresp.getcode()  
print”Elapsed time: %s”%(time.time()-start)    
get_responses()

The output is:
http://www.baidu.com200
http://www.amazon.com200
http://www.ebay .com200
http://www.alibaba.com200
http://www.jb51.net200
Elapsed time:3.0814409256

Explanation:
urls are requested in order
Unless the cpu gets a response from one url, it will not request the next url
The network request will take a long time, so the cpu is waiting for the return time of the network request has been idle.
Multi-threading

import urllib2 
import time 
from threading import Thread   
classGetUrlThread(Thread):   
def__init__(self, url):     
self.url=url     
super(GetUrlThread,self).__init__()      
defrun(self):     
resp=urllib2.urlopen(self.url)     
printself.url, resp.getcode()    
defget_responses():   urls=[     
‘http://www.baidu.com',     
‘http://www.amazon.com',     
‘http://www.ebay.com',     
‘http://www.alibaba.com',     
‘http://www.jb51.net'   
]   
start=time.time()   
threads=[]   
forurlinurls:     
t=GetUrlThread(url)     
threads.append(t)     
t.start()   
fortinthreads:     
t.join()   
print”Elapsed time: %s”%(time.time()-start)    
get_responses()

Output:
http://www.jb51.net200
http://www.baidu.com200
http://www.amazon.com200
http://www.alibaba.com200
http ://www.ebay.com200
Elapsed time:0.689890861511

Explanation:

Aware of the improvement in program execution time
We wrote a multi-threaded program to reduce the waiting time of the CPU. When we are waiting for a network request in a thread to return, the CPU can Switch to other threads to make network requests in other threads.
We expect one thread to process one url, so we pass a url when instantiating the thread class.
Thread running means executing the run() method in the class.
No matter what, we want each thread to execute run().
Create a thread for each URL and call the start() method, which tells the CPU to execute the run() method in the thread.
We want to calculate the time spent when all threads have finished executing, so we call the join() method.
join() can notify the main thread to wait for this thread to end before executing the next instruction.
We called the join() method on each thread, so we calculated the running time after all threads have completed execution.

About threads:

cpu may not execute the run() method immediately after calling start().
You cannot determine the execution order of run() among different threads.
For a single thread, it is guaranteed that the statements in the run() method are executed in order.
This is because the url in the thread will be requested first, and then the returned result will be printed.

Example 2

We will use a program to demonstrate resource competition between multi-threads and fix this problem.

from threading import Thread    
#define a global variable some_var=0   
classIncrementThread(Thread):   
defrun(self):     
#we want to read a global variable     
#and then increment it     
globalsome_var     
read_value=some_var     
print”some_var in %s is %d”%(self.name, read_value)     
some_var=read_value+1    
print”some_var in %s after increment is %d”%(self.name, some_var)    
defuse_increment_thread():   
threads=[]   
foriinrange(50):     
t=IncrementThread()     
threads.append(t)     
t.start()   
fortinthreads:     
t.join()   
print”After 50 modifications, some_var should have become 50″   
print”After 50 modifications, some_var is %d”%(some_var,)    
use_increment_thread()

Run this program multiple times and you will see a variety of different results.
Explanation:
There is a global variable and all threads want to modify it.
All threads should add this global variable 1 .
With 50 threads, the final value should become 50, but it does not.
Why didn’t it reach 50?
When some_var is 15, thread t1 reads some_var. At this time, the CPU gives control to another thread t2.
The some_var read by the t2 thread is also 15
Both t1 and t2 increase some_var to 16
What we expected at that time was t1 t2 two threads make some_var + 2 becomes 17
There is competition for resources here.
The same situation may also occur in other threads, so the final result may be less than 50.
Resolving resource competition

from threading 
import Lock, Thread 
lock=Lock() 
some_var=0   
classIncrementThread(Thread):   
defrun(self):     
#we want to read a global variable     
#and then increment it     
globalsome_var     
lock.acquire()     
read_value=some_var     
print”some_var in %s is %d”%(self.name, read_value)     
some_var=read_value+1    
print”some_var in %s after increment is %d”%(self.name, some_var)     
lock.release()    
defuse_increment_thread():   
threads=[]   
foriinrange(50):     
t=IncrementThread()     
threads.append(t)     
t.start()   
fortinthreads:     
t.join()   
print”After 50 modifications, some_var should have become 50″   
print”After 50 modifications, some_var is %d”%(some_var,)    
use_increment_thread()

Running the program again achieved the results we expected.
Explanation:
Lock Used to prevent race conditions
If thread t1 acquires the lock before performing some operations. Other threads will not perform the same operation before t1 releases the Lock
What we want to make sure is that once thread t1 has read some_var, other threads can not read some_var until t1 has finished modifying some_var
Read like this And modifying some_var becomes a logical atomic operation.
Example 3
Let us use an example to prove that one thread cannot affect variables (non-global variables) in other threads.
time.sleep() can suspend a thread and force thread switching to occur.

from threading import Thread 
import time    
classCreateListThread(Thread):   
defrun(self):     
self.entries=[]     
foriinrange(10):       
time.sleep(1)       
self.entries.append(i)     
printself.entries    
defuse_create_list_thread():   
foriinrange(3):     
t=CreateListThread()     
t.start()    
use_create_list_thread()

After running it a few times, I found that the results I was striving for were not printed out. While one thread is printing, the CPU switches to another thread, so incorrect results are produced. We need to make sure to print self.entries is a logical atomic operation to prevent printing from being interrupted by other threads.
We used Lock(), look at the example below.

from threading import Thread, Lock 
import time    
lock=Lock()    
classCreateListThread(Thread):   
defrun(self):     
self.entries=[]     
foriinrange(10):       
time.sleep(1)       
self.entries.append(i)     
lock.acquire()     
printself.entries     
lock.release()    
defuse_create_list_thread():   
foriinrange(3):     
t=CreateListThread()     
t.start()    
use_create_list_thread()

This time we saw the correct results. It proves that one thread cannot modify the internal variables (non-global variables) of other threads.

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
How do you slice a Python array?How do you slice a Python array?May 01, 2025 am 12:18 AM

The basic syntax for Python list slicing is list[start:stop:step]. 1.start is the first element index included, 2.stop is the first element index excluded, and 3.step determines the step size between elements. Slices are not only used to extract data, but also to modify and invert lists.

Under what circumstances might lists perform better than arrays?Under what circumstances might lists perform better than arrays?May 01, 2025 am 12:06 AM

Listsoutperformarraysin:1)dynamicsizingandfrequentinsertions/deletions,2)storingheterogeneousdata,and3)memoryefficiencyforsparsedata,butmayhaveslightperformancecostsincertainoperations.

How can you convert a Python array to a Python list?How can you convert a Python array to a Python list?May 01, 2025 am 12:05 AM

ToconvertaPythonarraytoalist,usethelist()constructororageneratorexpression.1)Importthearraymoduleandcreateanarray.2)Uselist(arr)or[xforxinarr]toconvertittoalist,consideringperformanceandmemoryefficiencyforlargedatasets.

What is the purpose of using arrays when lists exist in Python?What is the purpose of using arrays when lists exist in Python?May 01, 2025 am 12:04 AM

ChoosearraysoverlistsinPythonforbetterperformanceandmemoryefficiencyinspecificscenarios.1)Largenumericaldatasets:Arraysreducememoryusage.2)Performance-criticaloperations:Arraysofferspeedboostsfortaskslikeappendingorsearching.3)Typesafety:Arraysenforc

Explain how to iterate through the elements of a list and an array.Explain how to iterate through the elements of a list and an array.May 01, 2025 am 12:01 AM

In Python, you can use for loops, enumerate and list comprehensions to traverse lists; in Java, you can use traditional for loops and enhanced for loops to traverse arrays. 1. Python list traversal methods include: for loop, enumerate and list comprehension. 2. Java array traversal methods include: traditional for loop and enhanced for loop.

What is Python Switch Statement?What is Python Switch Statement?Apr 30, 2025 pm 02:08 PM

The article discusses Python's new "match" statement introduced in version 3.10, which serves as an equivalent to switch statements in other languages. It enhances code readability and offers performance benefits over traditional if-elif-el

What are Exception Groups in Python?What are Exception Groups in Python?Apr 30, 2025 pm 02:07 PM

Exception Groups in Python 3.11 allow handling multiple exceptions simultaneously, improving error management in concurrent scenarios and complex operations.

What are Function Annotations in Python?What are Function Annotations in Python?Apr 30, 2025 pm 02:06 PM

Function annotations in Python add metadata to functions for type checking, documentation, and IDE support. They enhance code readability, maintenance, and are crucial in API development, data science, and library creation.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment