CSIC_716_20191209【并发编程---GIL和协程】
GIL Global Interpreter Lock 全局解释锁
GIL对含IO的任务来说,会出现不能保证数据安全的情况。如下:
from threading import Thread
from threading import Lock
import time
n = 100
def task1():
global n
m = n
time.sleep(0.1)
n = m + 1
if __name__ == '__main__':
lock = Lock()
list1 = []
for line in range(5):
t1 = Thread(target=task1)
t1.start()
list1.append(t1)
for i in list1:
t1.join()
print(n)
打印的值为101,因为在线程遇到IO时,会被剥夺CPU执行权限,当IO结束时,不同线程的均取到最初的n值。
********************************************************************************************************************************
含有IO的涉及修改数据的任务,要加上线程互斥锁
from threading import Thread
from threading import Lock
import time n = 100
def task1():
global n
lock.acquire()
m = n
time.sleep(1)
n = m + 1
lock.release()
if __name__ == '__main__':
lock = Lock()
list1 = []
for line in range(5):
t1 = Thread(target=task1)
t1.start()
list1.append(t1)
for i in list1:
t1.join()
print(n)
结果为105,加了锁,将并发编程串行。
********************************************************************************************************************************
GIL对不含IO的任务来说,可以保证数据安全的情况。如下:
n = 100
def task1():
global n
m = n
n = m + 1
if __name__ == '__main__':
lock = Lock()
list1 = []
for line in range(5):
t1 = Thread(target=task1)
t1.start()
list1.append(t1)
for i in list1:
t1.join()
print(n)
结果为105,全局锁起到了线程锁的效果。
********************************************************************************************************************************
协程
协程用于在单线程下实现并发。
协程对IO密集型很有用,感觉是为了最大化利用操作系统分配给进程的时间片。
协程是手动实现IO切换+保存状态,去欺骗操作系统,让操作系统误以为没有发生IO。
使用第三方模块 gevent
# _*_ coding: gbk _*_
# @Author: Wonder
from gevent import monkey # monkey.patch_all 猴子补丁
from gevent import spawn # spawn() ,用于创建协程
from gevent import joinall # joinall[spawn1,spawn2,spawn3]
import time monkey.patch_all() def task1():
print('start......')
time.sleep(1)
print('end......') def task2():
print('start......')
time.sleep(1)
print('end......') if __name__ == '__main__':
sp1 = spawn(task1)
sp2 = spawn(task2)
joinall([sp1, sp2]) # 将join合并起来了,等到协程结束,再结束线程
monkey.patch_all( ),监听所有的任务是否有IO操作,并将IO转为gevent能识别的IO,一定要写在最前面,导入时就写。
spawn()提交协程 ,内部做了start()
joinall( [ sp1 , sp2 , ....] ) 将等待sp1,sp2协程结束
网络编程+并发编程 实例
SOCKET套接字通信,Server端用协程并发处理,Client端用线程并发访问。
SERVER 服务端
# _*_ coding: gbk _*_
# @Author: Wonder
import socket
from gevent import monkey
from gevent import spawn monkey.patch_all() def server(ip, port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((ip, port))
server.listen(5)
while True:
conn, addr = server.accept()
spawn(run, conn) # 协程 def run(conn):
while True:
try:
data = conn.recv(1024)
if not data:
break
print(data.decode('utf-8'))
conn.send('永不在线'.encode('utf-8'))
except Exception as e:
print(e)
break
conn.close() if __name__ == '__main__':
p1 = spawn(server, '127.0.0.1', 9527) # 协程
p1.join()
Client 客户端
# _*_ coding: gbk _*_
# @Author: Wonder
import socket
from concurrent.futures import ThreadPoolExecutor
from threading import current_thread def client(i):
cliet = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cliet.connect(
('127.0.0.1', 9527)
)
while True:
cliet.send(('NO_%s;线程号:%s' % (i, current_thread().getName())).encode('utf-8'))
data = cliet.recv(1024)
print(data.decode('utf-8')) if __name__ == '__main__':
pool = ThreadPoolExecutor(5)
for i in range(100):
pool.submit(client, i)
CSIC_716_20191209【并发编程---GIL和协程】的更多相关文章
- Python并发编程——多线程与协程
Pythpn并发编程--多线程与协程 目录 Pythpn并发编程--多线程与协程 1. 进程与线程 1.1 概念上 1.2 多进程与多线程--同时执行多个任务 2. 并发和并行 3. Python多线 ...
- python并发编程之线程/协程
python并发编程之线程/协程 part 4: 异步阻塞例子与生产者消费者模型 同步阻塞 调用函数必须等待结果\cpu没工作input sleep recv accept connect get 同 ...
- Python3 与 C# 并发编程之~ 协程篇
3.协程篇¶ 去年微信公众号就陆陆续续发布了,我一直以为博客也汇总同步了,这几天有朋友说一直没找到,遂发现,的确是漏了,所以补上一篇 在线预览:https://github.lesschina.c ...
- 15.python并发编程(线程--进程--协程)
一.进程:1.定义:进程最小的资源单位,本质就是一个程序在一个数据集上的一次动态执行(运行)的过程2.组成:进程一般由程序,数据集,进程控制三部分组成:(1)程序:用来描述进程要完成哪些功能以及如何完 ...
- Python并发编程系列之协程
1 引言 协程是近几年并发编程的一个热门话题,与Python多进程.多线程相比,协程在很多方面优势明显.本文从协程的定义和意义出发,结合asyncio模块详细讲述协程的使用. 2 协程的意义 2.1 ...
- python之并发编程(线程\进程\协程)
一.进程和线程 1.进程 假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I/O操作),而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源.是 ...
- python并发编程之gevent协程(四)
协程的含义就不再提,在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块.由于协程对于操作系统是无感知的,所以其切换需要程序员自己去完成. 系列文章 python并发编程 ...
- python并发编程之asyncio协程(三)
协程实现了在单线程下的并发,每个协程共享线程的几乎所有的资源,除了协程自己私有的上下文栈:协程的切换属于程序级别的切换,对于操作系统来说是无感知的,因此切换速度更快.开销更小.效率更高,在有多IO操作 ...
- GIL以及协程
GIL以及协程 一.GIL全局解释器锁 演示 ''' python解释器: - Cpython c语言 - Jpython java 1.GIL:全局解释器锁 - 翻译:在同一个进程下开启的多个线程, ...
随机推荐
- https://segmentfault.com/a/1190000009892006?utm_source=tuicool&utm_medium=referral
https://segmentfault.com/a/1190000009892006?utm_source=tuicool&utm_medium=referral
- Linux eth0, eth1, ..., eth%d 的生成【转】
转自:https://blog.csdn.net/xiruanliuwei/article/details/78765255 一直很好奇,Linux下的eth0, eth1,eth2等是如何生成的~ ...
- Ubuntu下的安装notepad++
Ubuntu下的安装方法: sudo add-apt-repository ppa:notepadqq-team/notepadqq sudo apt-get update sudo apt-get ...
- for循环语句示例
for循环语句示例 一判断/var/目录下所有文件的类型 完整脚本 [root@centos73 ~]# cat shell_scripts/filetype.sh #!/bin/bash #Auth ...
- shell脚本编程测试类型上
一bash的条件测试 判断某需求是否满足,需要由测试机制来实现.专用的测试表达式需要由测试命令辅助完成测试过程. 评估布尔声明,以便用在条件性执行中.若真,则返回0:若假,则返回1. 测试命令:• t ...
- padding 填充
CSS padding(填充)是一个简写属性,定义元素边框与元素内容之间的空间,即上下左右的内边距. padding(填充) 当元素的 padding(填充)内边距被清除时,所释放的区域将会受到元素背 ...
- PHP copy() 函数
定义和用法 copy() 函数复制文件. 该函数如果成功则返回 TRUE,如果失败则返回 FALSE. 语法 copy(file,to_file) 参数 描述 file 必需.规定要复制的文件. to ...
- ubuntu下共享wifi 使用kde5-nm-connection-editor
1.首先按照正常的建立方法把wifi建立好,然后在软件中心搜索 network ,点击安装 kde5-nm-connection-editor. 2.在终端里输入kde5-nm-connection- ...
- 极限IO优化
namespace IO{ #define BUF_SIZE 100000 #define OUT_SIZE 100000 #define ll long long //fread->read ...
- PHP基础知识总结(二) 数据类型、数组、变量和运算符
一.PHP是服务器端的脚本语言.在服务器端解析完成后,向前端浏览器发送html. PHP文件的部署位置在:xampp\htdocs文件夹下,当然这个位置可以修改.二.PHP基本语法 1.文件后缀名是p ...