Junior
214
What is concurrency?
Answer from AI
sobes.tech AI
Method of performing multiple tasks that may overlap in time.
- Parallelism: Tasks are executed simultaneously on different CPU cores.
- Concurrency: Tasks may be executed sequentially or interleaved on a single core, creating an illusion of simultaneity.
In Python, concurrency is often implemented using:
- Threads: Used for I/O operations (network, disk I/O), where a thread can "sleep" while waiting, allowing another thread to work. Due to GIL (Global Interpreter Lock), threads do not provide true parallelism for CPU-bound tasks in standard CPython.
- Processes: Used for CPU-bound tasks. Each process has its own independent address space, bypasses GIL, and provides true parallelism.
- Coroutines and Asynchronous Programming (asyncio): Lightweight tasks that cooperatively switch. Ideal for high-load I/O-bound applications.
| Mechanism | Usage | Parallelism (CPU-bound) | GIL (CPython) | Switching | Resource Costs |
|---|---|---|---|---|---|
| Threads | I/O-bound | No (due to GIL) | Affects | OS scheduler | High |
| Processes | CPU-bound, I/O-bound | Yes | Bypassed | OS scheduler | Very high |
| Coroutines | I/O-bound, High-load | No | No impact | Explicit (await) |
Low |
# Example of using threads for an I/O-bound task
import threading
import time
def download_data(url):
# Simulate network request
print(f"Starting download from {url}")
time.sleep(2) # Simulate I/O wait
print(f"Download from {url} completed")
urls = ["http://site1.com", "http://site2.com", "http://site3.com"]
threads = []
for url in urls:
thread = threading.Thread(target=download_data, args=(url,))
threads.append(thread)
thread.start()
for thread in threads:
thread.join() # Wait for all threads to finish
print("All downloads completed.")
# Example of using processes for CPU-bound tasks
import multiprocessing
import time
def calculate_square(number):
# Simulate CPU-bound calculation
print(f"Starting calculation of square for {number}")
result = number * number
time.sleep(1) # Simulate CPU work
print(f"Square of {number} - {result}")
return result
numbers = [1, 2, 3, 4]
pool = multiprocessing.Pool(processes=2) # Use 2 processes
results = pool.map(calculate_square, numbers)
pool.close()
pool.join()
print(f"All calculations finished. Results: {results}")
# Example of using asyncio for I/O-bound tasks
import asyncio
async def download_data_async(url):
# Simulate asynchronous network operation
print(f"Starting async download from {url}")
await asyncio.sleep(2) # Simulate async I/O wait
print(f"Async download from {url} completed")
async def main():
urls = ["http://site1.com", "http://site2.com", "http://site3.com"]
tasks = [download_data_async(url) for url in urls]
await asyncio.gather(*tasks) # Run tasks concurrently (cooperatively)
print("Starting async downloads...")
asyncio.run(main())
print("All async downloads completed.")
Concurrency allows efficient resource utilization, especially when involving I/O operations, avoiding CPU idle time.