多线程threading

多线程特点:

#线程的并发是利用cpu上下文的切换(是并发,不是并行)
#多线程执行的顺序是无序的
#多线程共享全局变量
#线程是继承在进程里的,没有进程就没有线程
#GIL全局解释器锁
#只要在进行耗时的IO操作的时候,能释放GIL,所以只要在IO密集型的代码里,用多线程就很合适
# 无序的,并发的
def test1(n):
time.sleep()
print('task', n) for i in range():
t = threading.Thread(target=test1,args=('t-%s' % i,))
t.start()
#计算并发所用的时间
import threading
import time def test1(n):
time.sleep()
print('task', n) def test2(n):
time.sleep()
print('task', n) start = time.time()
l = []
t1 = threading.Thread(target=test1, args=(,))
t2 = threading.Thread(target=test1, args=(,))
t1.start()
t2.start()
l.append(t1)
l.append(t2)
for i in l:
i.join()
end = time.time()
print(end - start)

GIL的全称是:Global Interpreter Lock,意思就是全局解释器锁,这个GIL并不是python的特性,他是只在Cpython解释器里引入的一个概念,而在其他的语言编写的解释器里就没有这个GIL例如:Jython,Pypy

为什么会有gil?:

随着电脑多核cpu的出现核cpu频率的提升,为了充分利用多核处理器,进行多线程的编程方式更为普及,随之而来的困难是线程之间数据的一致性和状态同步,而python也利用了多核,所以也逃不开这个困难,为了解决这个数据不能同步的问题,设计了gil全局解释器锁。

说到gil解释器锁,我们容易想到在多线程中共享全局变量的时候会有线程对全局变量进行的资源竞争,会对全局变量的修改产生不是我们想要的结果,而那个时候我们用到的是python中线程模块里面的互斥锁,哪样的话每次对全局变量进行操作的时候,只有一个线程能够拿到这个全局变量;看下面的代码:

import threading
global_num = def test1():
global global_num
for i in range():
global_num += print("test1", global_num) def test2():
global global_num
for i in range():
global_num += print("test2", global_num) t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
t1.start()
t2.start()
在上面的例子里,我们创建了两个线程来争夺对global_num的加一操作,但是结果并非我们想要的,所以我们在这里加入了互斥锁 import threading
import time
global_num = lock = threading.Lock() def test1():
global global_num
lock.acquire()
for i in range():
global_num +=
lock.release()
print("test1", global_num) def test2():
global global_num
lock.acquire()
for i in range():
global_num +=
lock.release()
print("test2", global_num) t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
start_time = time.time() t1.start()
t2.start()

多进程multiprocessing

#一个程序运行起来之后,代码+用到的资源称之为进程,它是操作系统分配资源的基本单位,不仅可以通过线程完成多任务,进程也是可以的
#进程之间是相互独立的
#cpu密集的时候适合用多进程

#进程之间不共享
import multiprocessing
from multiprocessing import Pool
import time
import threading
g_num =
def edit():
global g_num
for i in range():
g_num += def reader():
print(g_num) if __name__ == '__main__':
p1 = multiprocessing.Process(target=edit)
p2 = multiprocessing.Process(target=reader())
p1.start()
p2.start()
p1.join()
p2.join()
#多进程并发
import multiprocessing
from multiprocessing import Pool
import time
def test1():
for i in range():
time.sleep()
print('test', i) def test2():
for i in range():
time.sleep()
print('test', i) if __name__ == '__main__':
p1 = multiprocessing.Process(target=test1)
p2 = multiprocessing.Process(target=test2)
p1.start()
p2.start()
#进程池
import multiprocessing
from multiprocessing import Pool
import time
import threading
g_num =
def test1(n):
for i in range(n):
time.sleep()
print('test1', i) def test2(n):
for i in range(n):
time.sleep()
print('test2', i)
def test3(n):
for i in range(n):
time.sleep()
print('test3', i) def test4(n):
for i in range(n):
time.sleep()
print('test4', i) if __name__ == '__main__':
pool = Pool()#把进程声明出来括号里不写东西说明无限制,如果写数字,就是最大的进程数
pool.apply_async(test1,(,))#用pool去调用函数test1,参数为10格式为(,)
pool.apply_async(test2,(,))#用pool去调用函数test2,参数为10格式为(,)
pool.apply_async(test3,(,))#用pool去调用函数test3,参数为10格式为(,)
pool.apply_async(test4,(,))#用pool去调用函数test4,参数为10格式为(,)
pool.close()#close必须在join的前面
pool.join()

协程并发(gevent)

# 异步IO
# 进程是资源分配的单位
# 线程是操作系统调度的单位
# 进程切换需要的资源最大,效率低
# 线程切换需要的资源一般,效率一般
# 协程切换任务资源很小,效率高
# 多进程、多线程根据cpu核数不一样可能是并行的,但是协成在一个线程中
#协程,自动切换
import gevent,time
from gevent import monkey
monkey.patch_all()
def test1():
for i in range():
time.sleep()
print('test1', ) def test2():
for i in range():
time.sleep()
print('test2', ) g1 = gevent.spawn(test1)
g2 = gevent.spawn(test2)
g1.join()            #开启
g2.join()
#server端
import gevent
from gevent import socket, monkey
monkey.patch_all()
def server_recv_conn(port):
s = socket.socket()
s.bind(('0.0.0.0', port))
s.listen()
while True:
conn, addr = s.accept()
g = gevent.spawn(recv_request, conn)
g.join()
def recv_request(conn):
while True:
data = conn.recv()
data = data.decode('utf-8')
print("recv:", data)
conn.send(data.upper().encode('utf-8')) if __name__ == '__main__':
server_recv_conn() #client端
import socket HOST = 'localhost'
PORT =
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
msg = input("==>:")
s.send(msg.encode('utf-8'))
data = s.recv()
print('接收:', data.decode('utf-8'))
s.close()
 

python第八章:多任务--小白博客的更多相关文章

  1. python之yagmail模块--小白博客

    yagmail 实现发邮件 yagmail 可以简单的来实现自动发邮件功能. 安装 pip install yagmail 简单例子 import yagmail #链接邮箱服务器 yag = yag ...

  2. 这几天有django和python做了一个多用户博客系统(可选择模板)

    这几天有django和python做了一个多用户博客系统(可选择模板) 没完成,先分享下 断断续续2周时间吧,用django做了一个多用户博客系统,现在还没有做完,做分享下,以后等完善了再慢慢说 做的 ...

  3. python环境变量配置 - CSDN博客

    一.下载: 1.官网下载python3.0系列(https://www.python.org/) 2.下载后图标为: 二.安装: Window下: 1.安装路径: 默认安装路径:C:\python35 ...

  4. Python爬虫简单实现CSDN博客文章标题列表

    Python爬虫简单实现CSDN博客文章标题列表 操作步骤: 分析接口,怎么获取数据? 模拟接口,尝试提取数据 封装接口函数,实现函数调用. 1.分析接口 打开Chrome浏览器,开启开发者工具(F1 ...

  5. python网络爬虫 新浪博客篇

    上次写了一个爬世纪佳缘的爬虫之后,今天再接再厉又写了一个新浪博客的爬虫.写完之后,我想了一会儿,要不要在博客园里面写个帖子记录一下,因为我觉得这份代码的含金量确实太低,有点炒冷饭的嫌疑,就是把上次的代 ...

  6. 用Python和Django实现多用户博客系统(二)——UUBlog

    这次又更新了一大部分功能,这次以app的形式来开发. 增加博客分类功能:博客关注.推荐功能(ajax实现) 增加二级频道功能 更多功能看截图及源码,现在还不完善,大家先将就着看.如果大家有哪些功能觉的 ...

  7. 在 Windows Azure 网站上使用 Django、Python 和 MySQL:创建博客应用程序

    编辑人员注释:本文章由 Windows Azure 网站团队的项目经理 Sunitha Muthukrishna 撰写. 根据您编写的应用程序,Windows Azure 网站上的基本Python 堆 ...

  8. Python开发【项目】:博客后台

    概述 通过自己写的博客后台代码.思路,来与武sir的代码进行一个差异化的比较,记录之间的差距,改善以后写代码的思路 博客后台这个项目,对之前Django学习的各个知识点都有涉及到,非常重要 用户登录验 ...

  9. python关于Django搭建简单博客项目(详解一)

    上一篇我们说了如何搭建简易博客网站,下面我们来进行详细解答.本文没有特定顺序,请结合上一篇和源代码参照学习. 相关源代码和解析请参看:https://github.com/Cheng0829/mysi ...

随机推荐

  1. Python输出和输入

    一.input()函数 在 Python 中,使用内置函数 input()可以接收用户的键盘输入. input()函数的基本用法如 下: variable = input("提示文字") 其中,var ...

  2. c/c++ 图的创建(二维数组法)

    c/c++ 图的创建(二维数组法) 图的概念 图由点和线组成 知道了图中有多少个点,和哪些点之间有线,就可以把一张图描绘出来 点之间的线,分有方向和无方向 创建图 创建图,实际就是创建出节点,和节点之 ...

  3. PHP中的Session工作原理

    一直在使用session存储数据,一直没有好好总结一下session的使用方式以及其工作原理,今天在这里做一下梳理. 这里的介绍主要是基于php语言,其他的语言操作可能会有差别,但基本的原理不变. 1 ...

  4. 数组实例的 copyWithin()

    用途:在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组.也就是说,使用这个方法,会修改数组本身. 用法:Array.prototype.copyWithin(targ ...

  5. LeetCode算法题-Pascal's Triangle II(Java实现)

    这是悦乐书的第171次更新,第173篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第30题(顺位题号是119).给定非负索引k,其中k≤33,返回Pascal三角形的第k ...

  6. June 12. 2018 Week 24th. Tuesday

    Just be yourself because you are unique and you will shine. 每个人都是独一无二的,做好你自己,你也能够光芒四射. From What a G ...

  7. C语言 投票系统:给定候选人,从键盘输入候选人的名字,统计票数,并输出最终获胜者

    投票系统:给定候选人名单,从键盘输入候选人的名字,统计票数,并输出最终获胜者.若投票人输入的名字不在其候选名单上,则该票数无效. //凯鲁嘎吉 - 博客园 http://www.cnblogs.com ...

  8. SpringCloud之初识Robbin---负载均衡

    在上一篇中讲解Eureka注册中心的案例,我们启动了一个user-service,然后通过DiscoveryClient来获取服务实例信息,然后获取ip和端口来访问. 但是实际环境中,我们往往会开启很 ...

  9. 《Java大学教程》—第14章 抽象、继承和接口

    自测题:1.    解释抽象和抽象数据类型的概念.P333抽象的概念是仅仅关注对象可以完成什么工作,而不必担心如何完成工作的细节.类模板通常被称为抽象数据类型.因为这类数据暴露给用户的所有信息仅仅是方 ...

  10. C. Ayoub and Lost Array cf dp

    C. Ayoub and Lost Array time limit per test 1 second memory limit per test 256 megabytes input stand ...