python入门(2-2)

目录:

1,Python同步异步编程




一、异步编程

异步编程常用组件(asyncio 模块)注意asyncio是协程,通过事件循环来实现,单线程并发一个线程内通过协程切换实现并发,任一时刻只有一个协程在运行。

  1. asyncio.gather(*coros):并发执行多个协程,等待所有协程完成,返回所有结果的列表(按传入顺序)。
  2. asyncio.create_task(coro):创建异步任务(Task 对象),将协程加入事件循环,无需立即等待,可实现 “后台” 执行。

asyncio.gather:

import asyncio
import time

# 异步耗时任务(协程函数,模拟IO等待)
async def async_task(name, delay):
print(f"异步任务 {name} 开始执行,延迟 {delay} 秒")
await asyncio.sleep(delay) # 异步等待(非阻塞,事件循环可切换其他任务)
print(f"异步任务 {name} 执行完成")
return f"任务 {name} 结果"

# 主协程函数
async def main():
start_time = time.time()
# 方式1:并发执行两个异步任务(使用 asyncio.gather())
result1, result2 = await asyncio.gather(
async_task("A", 2),
async_task("B", 3)
)
end_time = time.time()
print(f"结果1:{result1},结果2:{result2}")
print(f"总耗时:{end_time - start_time:.2f} 秒") # 总耗时约3秒(取最长任务的时间)

if __name__ == "__main__":
asyncio.run(main()) # 启动事件循环,运行主协程

asyncio.createtask:

async def main():
start_time = time.time()
# 创建任务,加入事件循环
task1 = asyncio.create_task(async_task("A", 2))
task2 = asyncio.create_task(async_task("B", 3))
# 可先执行其他同步/异步操作
print("主协程:先执行一些其他操作")
await asyncio.sleep(1)
# 等待任务完成,获取结果
result1 = await task1
result2 = await task2
end_time = time.time()
print(f"总耗时:{end_time - start_time:.2f} 秒") # 总耗时约3秒

异步编程常用组件(threading 模块)注意threading是多线程,开销较大,真并行(在多核CPU上)。操作系统调度线程,可在不同核心同时运行。

import threading
import time

def worker(name, delay):
"""线程任务函数"""
print(f"线程 {name} 开始")
time.sleep(delay)
print(f"线程 {name} 结束")
return f"结果-{name}"

# === 创建线程 ===
t1 = threading.Thread(target=worker, args=("A", 2))
t2 = threading.Thread(target=worker, args=("B", 1))

t1.start() # 启动线程
t2.start()

t1.join() # 等待线程结束
t2.join()

print("所有线程完成")

# === 线程锁(解决资源竞争)===
counter = 0
lock = threading.Lock()

def safe_increment():
global counter
for _ in range(100000):
with lock: # 自动获取和释放锁
counter += 1

threads = []
for i in range(5):
t = threading.Thread(target=safe_increment)
threads.append(t)
t.start()

for t in threads:
t.join()

print(f"最终计数: {counter}") # 应该是500000

思考:在python中有多线程造成资源竞争需要加锁,但是在web worker中为什么没有提到呢?

这是一个非常深刻的问题,根本原因在于:JavaScript(特指浏览器环境和标准的Node.js)的并发模型与Python的多线程有本质区别——JavaScript默认没有真正的“共享内存”线程。

Python threading (多线程)中,共享内存。所有线程共享同一进程的内存空间,可以直接读写同一变量。而在JavaScript Web Worker 中内存隔离。每个Worker有独立的、隔离的内存空间(堆、栈、全局对象)。通过 postMessage 发送消息,通过 onmessage 事件接收。数据是复制转移的,不是直接共享。所以如果你开启了多个web worker虽然不用加锁但是不要对同一个变量拿过来直接给返回结果进行赋值,不然也有可能会造成问题!


2026.1.1 晚10点

互联网行业信息家