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和协程】的更多相关文章

  1. Python并发编程——多线程与协程

    Pythpn并发编程--多线程与协程 目录 Pythpn并发编程--多线程与协程 1. 进程与线程 1.1 概念上 1.2 多进程与多线程--同时执行多个任务 2. 并发和并行 3. Python多线 ...

  2. python并发编程之线程/协程

    python并发编程之线程/协程 part 4: 异步阻塞例子与生产者消费者模型 同步阻塞 调用函数必须等待结果\cpu没工作input sleep recv accept connect get 同 ...

  3. Python3 与 C# 并发编程之~ 协程篇

      3.协程篇¶ 去年微信公众号就陆陆续续发布了,我一直以为博客也汇总同步了,这几天有朋友说一直没找到,遂发现,的确是漏了,所以补上一篇 在线预览:https://github.lesschina.c ...

  4. 15.python并发编程(线程--进程--协程)

    一.进程:1.定义:进程最小的资源单位,本质就是一个程序在一个数据集上的一次动态执行(运行)的过程2.组成:进程一般由程序,数据集,进程控制三部分组成:(1)程序:用来描述进程要完成哪些功能以及如何完 ...

  5. Python并发编程系列之协程

    1 引言 协程是近几年并发编程的一个热门话题,与Python多进程.多线程相比,协程在很多方面优势明显.本文从协程的定义和意义出发,结合asyncio模块详细讲述协程的使用. 2 协程的意义 2.1 ...

  6. python之并发编程(线程\进程\协程)

    一.进程和线程 1.进程 假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I/O操作),而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源.是 ...

  7. python并发编程之gevent协程(四)

    协程的含义就不再提,在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块.由于协程对于操作系统是无感知的,所以其切换需要程序员自己去完成. 系列文章 python并发编程 ...

  8. python并发编程之asyncio协程(三)

    协程实现了在单线程下的并发,每个协程共享线程的几乎所有的资源,除了协程自己私有的上下文栈:协程的切换属于程序级别的切换,对于操作系统来说是无感知的,因此切换速度更快.开销更小.效率更高,在有多IO操作 ...

  9. GIL以及协程

    GIL以及协程 一.GIL全局解释器锁 演示 ''' python解释器: - Cpython c语言 - Jpython java 1.GIL:全局解释器锁 - 翻译:在同一个进程下开启的多个线程, ...

随机推荐

  1. Codeforces 1195E. OpenStreetMap (单调队列)

    题意:给出一个n*m的矩形.询问矩形上所有的a*b的小矩形的最小值之和. 解法:我们先对每一行用单调栈维护c[i][j]代表从原数组的mp[i][j]到mp[i][j+b-1]的最小值(具体维护方法是 ...

  2. Codeforces 354B 博弈, DP,记忆化搜索

    题意:现在有一个字符矩阵,从左上角出发,每个人交替选择一个字符.如果最后字符a数目大于字符b,那么第一个人获胜,否则b获胜,否则平均.现在双方都不放水,问最后结果是什么? 思路:这题需要注意,选择的字 ...

  3. mysql的几种锁

    由于对于mysql的锁机制了解的并不深入,所以翻阅了资料,整理一下自己所理解的锁.以mysql数据库的InnoDB引擎为例,因为InnoDB支持事务.行锁.表锁:且现在大部分公司使用的都是InnoDB ...

  4. logback-paycore.xml 日志配置

    <?xml version="1.0" encoding="UTF-8"?><configuration> <property n ...

  5. egg 的学习

    1.初始化项目 快速生成项目: $ npm i egg-init -g $ egg-init egg-example --type=simple $ cd egg-example $ npm i 启动 ...

  6. 【串线篇】实现一个RestfulCRUD

    一.概述 利用SpringMVC做一个CRUD(增删改查)符合Rest风格的: C:Create:创建 R:Retrieve:查询 U:Update:更新 D:Delete:删除 <%@tagl ...

  7. OpenLayers学习笔记(十二)— 飞机速度矢量线预测(二)

    根据计算公式实现预测线 作者:狐狸家的鱼 GitHub:八至 之前有一篇博客简单写了一个模拟demo,根据物体当前的速度和方向预测多少时间后所在的位置,具体计算是参考<(译)计算距离.方位以及更 ...

  8. PostgreSQL按年月日分组(关键词:extract time as Year/Month/Day)

    Select EXTRACT(year from cast(joindate as timestamp)) as Year, EXTRACT(month from cast(joindate as t ...

  9. 洛谷P2786 英语1(eng1)- 英语作文

    题目背景 蒟蒻HansBug在英语考场上,挠了无数次的头,可脑子里还是一片空白. 题目描述 眼下出现在HansBug蒟蒻面前的是一篇英语作文,然而智商捉急的HansBug已经草草写完了,此时 他发现离 ...

  10. 【LeetCode 34】在排序数组中查找元素的第一个和最后一个位置

    题目链接 [题解] 二分某个数的上下界. 其实这个方法并不难. 只要你想清楚了二分最后一次执行的位置在什么地方就不难了. [代码] class Solution { public: vector< ...