python中的多线程非常的常用,之前一直糊里糊涂地使用,没有一些系统性的概念,记录一下~

0x001 多线程的优势:可将长时间占用的程序放到后台

可能会加速程序执行速度

能够实现一些类似同步执行的效果

0x002 线程线程是OS的执行单元

每个独立的线程都有一个程序运行的入口、顺序执行序列和程序出口,线程不能离开程序独立执行。

每个线程都有自己唯一的一组CPU寄存器(上下文),反映了线程上次运行时该CPU寄存器的状态。线程中指令指针和堆栈指针寄存器非常重要,线程在进程中得到上下文,这些地址用于标志拥有线程的进程地址空间中的内存

线程可被抢占

线程退让

0x01 分类:名字

说明

用户线程

不需内核支持而在用户程序中实现的线程

内核线程

操作系统内核创建和撤销

0x02 Py3中的threading模块:方法

说明

threading.current_thread()

返回当前的线程变量

threading.enumerate()

返回正在运行线程的list(启动后,结束前)

threading.active_count

等于len(threading.enumerate())

提供了 Thread类,所以还可以

方法

说明

run()

表示线程活动的方法

start()

启动线程活动

join([time])

阻塞式等待线程终止

isAlive()

线程是否活动

getName()

返回线程名

setName()

设置线程名

# -*- coding:utf-8 -*-

# 多线程

# DYBOY

# time:2019-3-10 09:37:48

import threading

import time

def printNum(endNum):

for i in range(1,endNum+1):

print(i, time.time())

# 创建线程

t = threading.Thread(target=printNum, name='printThread', args=(10,))

t.start()

t.join()

print("线程%s结束" % threading.current_thread().name)

0x003 多线程&多进程&线程锁多进程中同一变量,各自有拷贝到自己的进程中,互不影响,多线程中,变量由多个线程共享,因此多线程中变量的同步就需要的到控制

lock = threading.Lock()

def runThread():

for i in range(1000):

lock.acquire()

try:

#....执行函数

finally:

lock.release()

# -*- coding:utf-8 -*-

# 多线程

# DYBOY

# time:2019-3-10 09:37:48

import threading

import time

money = 0

lock = threading.Lock()

def chaneMoney(num):

global money

money += num

money -= num

def runThread(n):

for i in range(1000):

lock.acquire()

try:

chaneMoney(n)

finally:

lock.release()

t1 = threading.Thread(target=runThread, args=(100,))

t2 = threading.Thread(target=runThread, args=(50,))

t1.start()

t2.start()

t1.join()

t2.join()

print("余额:",money)

ps: 在实际的运行中,发现似乎线程锁没有起到作用,在线程中的join() 方法似乎是有影响的,

join():阻塞当前进程/线程,直到调用join方法的那个进程执行完,再继续执行当前进程。相当于线程守护,直到调用join()方法的线程执行完毕,才将控制权交给主进程。

0x04 问题?

从上,看到多线程中为了保证数据的一致性,使用了线程锁来实现类似同步的功能,然而这样反而多了获取锁和释放锁的步骤,所以在我看来。线程也没有加快程序的运行时间。

一个程序从执行到结束,首先会创建一个主进程,os的执行单元是线程,一个进程有至少一个或多个线程来实现其功能,在线程的创建和上下文切换是一个比较大的开销,提升多线程的优势就需要从其中来考虑:

无锁并发(减少数据关联度,更合理优化的实现方式)

减少并发(线程不能无限制的多)

减少上下文切换的开销(协程)

0x05 协程函数调用的时候,是使用栈的方式,比如A调用B,B调用C,C执行返回给B,B执行完后返回给A,是一个压栈出栈的过程

子程序(函数),总是一个入口,一次返回,调用的顺序永远如此,所以如果有比较频繁的函数调用,那么就用较多的上下文切换时间,利用协程(微线程)可以较好解决这个问题。

协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。(多进程)

# -*- coding:utf-8 -*-

# 协程 gevent

# DYBOY

# time:2019-3-10 09:37:48

# description: 下载图片到本地(普通版本)

# from gevent import monkey

# monkey.patch_all()

import requests,time,json

def get_save_pic(picUrl, name):

img = requests.get(picUrl)

with open('pic/'+name,'wb') as f:

f.write(img.content)

return None

if __name__ == '__main__':

sT = time.time()

jsonData = requests.get('http://img.top15.cn/piclist.php')

jsonData = json.loads(jsonData.text)

imgs = jsonData['data']

for img in imgs:

get_save_pic(img[0], img[1])

print("Success", time.time() - sT)

网络效果好的时候:

# -*- coding:utf-8 -*-

# 协程 gevent

# DYBOY

# time:2019-3-10 09:37:48

# description: 下载图片到本地

from gevent import monkey

monkey.patch_all()

import gevent,requests,time,json

def get_save_pic(picUrl, name):

img = requests.get(picUrl)

with open('pic/'+name,'wb') as f:

f.write(img.content)

return None

if __name__ == '__main__':

startTime = time.time()

jsonData = requests.get('http://img.top15.cn/piclist.php')

jsonData = json.loads(jsonData.text)

imgs = jsonData['data']

targetLists = []

for img in imgs:

targetLists.append(gevent.spawn(get_save_pic, img[0], img[1]))

gevent.joinall(targetLists)

print("Success!", time.time()-startTime)

# 不知道什么原因,没有输出,但是从执行的结果上来看

# 最后,所有图片同时在文件夹生成,非常迅速

2019-3-10 22:05:04 在命令行下可正常执行!

从肉眼可见的角度来看,还是协程的效果更好(在数据量不大下,感觉比较而得出的结论还是不是很有说服力,在数据量大的情况下,线程不能无限增加,协程的效果表现更优异,再加上多进程应该就更NICE了)。

0x06 总结

本次探究的是多线程与协程的区别,多线程不能无限创建,所以有的时候创建多线程在生产环境下是不可行的,在爬虫下载图片这部分是可以使用多线程去下载,多线程其实也是一个等待执行的过程,其与协程的差别主要是在上下文切换上,协程减少了上下文切换的时间,是程序自己控制的,而多线程的上下文切换是需要系统调用会耗费更多的时间,本次例子实现中使用了monkey这个模块,还不清楚其中遇到的输出问题,继续探究!

python进程线程协程区别_Python3多线程与协程相关推荐

  1. python/进程线程的总结

    python/进程线程的总结 一.进程和线程的描述:进程:最小的资源管理单位线程:最小的执行单位执行一个进程时就默认执行一个线程(主线程)进程和线程的工作方式:串行:假如共有A.B.C任务, 串行的执 ...

  2. python进程线程协程区别_进程和线程、协程的区别

    现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中有协程库gevent,py web框架tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区 ...

  3. python进程线程协程区别_Python中 进程 线程 协程

    一.进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在 ...

  4. python 进程 线程 协程

    并发与并行:并行是指两个或者多个事件在同一时刻发生:而并发是指两个或多个事件在同一时间间隔内发生.在单核CPU下的多线程其实都只是并发,不是并行. 进程是系统资源分配的最小单位,进程的出现是为了更好的 ...

  5. python多线程协程配合使用_多线程配合协程

    协程配合线程 asyncio.run_coroutine_threadsafe 该方法的语法如下: asyncio.run_coroutine_threadsafe(coro, loop) 其实在协程 ...

  6. Python爬虫纯干货:单线程、多线程和协程的爬虫性能对比

    今天我要给大家分享的是如何爬取豆瓣上深圳近期即将上映的电影影讯,并分别用普通的单线程.多线程和协程来爬取,从而对比单线程.多线程和协程在网络爬虫中的性能. 具体要爬的网址是:https://movie ...

  7. linux c进程线程的面试问题,linux 多线程面试题_linux进程线程_linux 线程 pthread_create...

    你写了一个简单的mandelbrot set程序,也就是说用ps命令行是可以看见多个线程,win32里同一个进程里各个线程之间是共享数据段的,win32的进程管理方式与unix上有着很大区别.adob ...

  8. python coroutine,go routine对比--理解多线程、协程

    1. 线程实现模型 线程的实现模型主要有3种:内核级线程模型.用户级线程模型和混合型线程模型.它们之间最大的区别在于线程与内核调度实体KSE(Kernel Scheduling Entity)之间的对 ...

  9. python线程按照顺序执行_Python3多线程之间的执行顺序问题

    from threading importThread, Lock#由_acquire解锁执行后释放_release锁 def _print(_id: str, _acquire: Lock, _re ...

最新文章

  1. 使用OneFlow搭建神经网络
  2. 智能车竞赛技术报告 | 双车接力组 - 黑龙江工程学院 - 睿龙二队
  3. 2021湖南高考成绩分段查询,2021年湖南高考分数一分一段位次表,湖南高考个人成绩排名查询方法...
  4. java刘保_[SSH] Eclipse+Struts2的简单应用
  5. 删除某个目录及目录下的所有子目录和文件
  6. linux怎么修改内存缓存,Linux内存、缓存、Swap等修改
  7. 手机型号大全_《华为手机型号大全》值得收藏
  8. 计算机辅助翻译课程用书,计算机辅助翻译本科课程教学大纲翻译本科
  9. 使用pandas计算环比、同比
  10. 【LaTeX】LaTeX常见括号总结
  11. PHP网页表单输入框输入字符简体繁体互转(非JS)
  12. 1405:三元一次方程
  13. STM32学习之SPI协议(读写FLASH)
  14. 全球各个国家名的英文
  15. JAVA程序设计基础05循环结构
  16. ConvMAE实战:使用ConvMAE实现对植物幼苗的分类(非官方)(一)
  17. py sel采集部署linux报错
  18. Linux脚本 括号,linux shell取小括号()、中括号[]、大括号{}等里的内容
  19. 解除华为学生模式的6种方法
  20. Python socket模块

热门文章

  1. 将传统的落后WAN转换为SD-WAN
  2. 使用DbVisualizer连接和管理金仓数据库
  3. App.config/Web.config 中特殊字符的处理
  4. selenium之 chromedriver与chrome版本映射表(更新至v2.33)
  5. 你所不知道的SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧(转)...
  6. winform groupbox控件放到窗体中间位置
  7. ZeroMQ接口函数之 :zmq_msg_init_data - 从一个指定的存储空间中初始化一个ZMQ消息对象的数据...
  8. C# 4.0 新增特性
  9. WINCE的内存配置
  10. Cortex-M家族发展史,简述Cortex-M0~M4的各个优势