在高并发场景下,提供了多线程模块,但是这个模块似乎并不能令人满意,因为它本身有全局解析锁(GIL)的问题。实际执行一段时间是单线程的。 。同时,还存在资源竞争的问题。 .4之后,引入了基于生成器对象的协程概念。即模块。除了模块之外,针对高并发问题还提出了其他解决方案,例如 和 都实现了类似的功能。这为节目选择提供了更多的可能性。下面是模块与模块的对比测试实验。我希望在另一篇文章中写模块的具体使用。
1. 模块
模块中的线程密集型操作竞争变量测试
代码:
#多线程共享数据争用检测
从 ,(x):
time.sleep(x)for b in range(1,51): #从 1+...+50 计算
a+=((),":",a)
a=0
=[]for i in range(1,20000): #为了突出效果,线程数开到接近20000
= (=,参数=(1,))
。()为了 :
。开始()
提取部分结果::
:
:
:
:
:
:
:运行时间:6。
6.
7.平均运行时间:7.0秒
从结果可以看出,当多线程进行密集型操作(占用大量CPU计算单元)时,同一个变量的数据会不一致。这就是所谓的“种族问题”。
2. 模块
该模块经过了密集型操作的测试(线程安全!不存在资源竞争),因此协程对密集型操作和IO并发有很强的支持。
代码:
#密集计算测试
a=0
任务=[]
数量=0
(x):#num += 1 # 思路3:num自增的不同位置(阻塞前/阻塞后)会产生不同的结果。
wait .sleep(x)for b in range(1,51): #从 1+...+50 计算
a+=b
num+= 1 #想法 1
print("这是 ",":",num,a) #想法 1,想法 3
print("这是 ",":",x,a) #想法 2
for i in range(1,20000): #即使休眠时间很短,大部分计算也不会造成资源争用。
= (1) #IDEA1# = (i*0.01) #IDEA2# = (3//i) #IDEA3
任务.(.())
loop= .() #创建事件循环
loop.(.wait(tasks)) #将协程放入事件循环中
代码实现思路:
(1)思路一:各个协程的休眠时间相同,也就是说几乎同时运行密集计算,并使用num自增计算作为协程的代号。
(2)想法二:为了区分不同协程占用CPU的运行时间片,我对睡眠时间进行了乘法运算。协程码号越大的协程休眠时间越长,将该时间作为协程码号。记录。
(3)想法3:这次我会对睡眠时间进行调整,使用除法运算。也就是说,协程代码越大,休眠时间越短。不过,这次协程代码是用num记录的,放在睡觉前(阻塞)。
提取前几个数据
思路一:当设置的睡眠时间(阻塞时间)相同时,结果的打印几乎同时出现。
: 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 10200
想法1运行时间:3.48584
3.8408
3.1382平均运行时间3.08秒
思路2:当设置的睡眠时间(阻塞时间)不同时,协程代码就是睡眠时间
: 0.01 : 0.02 : 0.03 : 0.04 : 0.05 : 0.06 : 0.07 : 0.08 10200
从上面两组数据可以看出,无论协程是同时执行还是分时段执行,都是严格按顺序执行的。想法2的结果非常符合我们的认知常识,那么想法1的结果是怎么来的呢?原因是在多并发的情况下(这里使用密集操作来模拟一系列并发的内部操作),被阻塞的协程会被暂时搁置,切换到另一个协程。协程的运行可以理解为队列。当大量协程到来时,它们无法立即执行,因此将它们放入一个类似队列的容器()中,并不断检测队列中哪个协程处于非阻塞状态。 ,调用该协程的资源并运行它。队列中的每个元素互不干扰。于是,就出现了上面的结果——有序的协程运行。
想法3:看下面这组数据
: 1999 : 1999 : 1999 : 1999 : 1999 : 1999 : 1999 : 1999 10200
为什么所有协程编号都相同?
因为最大协程号睡眠时间最短,先执行输出,而且协程号是累加的,所以后面执行的线程会被标记为最大协程号。由此进一步可以看出
3、性能对比
完成时间对比:
:平均运行时间:7.0秒
:平均运行时间3.08秒
从上面多线程模块和协程模块的对比可以看出,完成时间大约是一半。因此在高并发情况下具有更大的优势,并且在资源保护方面也做得更好。
扫一扫在手机端查看
我们凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求,请立即点击咨询我们或拨打咨询热线: 13761152229,我们会详细为你一一解答你心中的疑难。