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. VUE前端面试题

    什么是 mvvm? MVVM 是 Model-View-ViewModel 的缩写.mvvm 是一种设计思想.Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑:View ...

  2. Electron-vue实战(二)— 请求Mock数据渲染页面

    Electron-vue实战(二)— 请求Mock数据渲染页面 作者:狐狸家的鱼 本文链接 GitHub:sueRimn 一.环境搭建 1.安装Mock.js 如果仅仅用作脱离后台的模拟数据,就安装在 ...

  3. QTcpSocket学习

    一.涉及到的函数 监听:tcpServer->listen(QHostAddress::LocalHost, 6666) 错误信息:tcpServer->errorString() 新连接 ...

  4. 2018icpc沈阳/gym101955 J How Much Memory Your Code Is Using? 签到

    题意: 给你定义一堆变量,计算一下这些变量共占了多少k内存. 题解: 按题意模拟即可,善用ceil() // // Created by melon on 2019/10/22. // #includ ...

  5. 2019ccpc秦皇岛/Gym102361 F Forest Program 仙人掌上dfs

    题意: 某地沙漠化严重,沙漠里长了很多仙人掌,现在要让你删掉仙人掌的一些边让它的所有连通分量都是树,就完成了沙漠绿化(什么鬼逻辑?)让你计算删边的方案数. 仙人掌是一种特殊的图,它的每一条边只属于1或 ...

  6. c 语言 volatile 关键字

    一.前言 1.编译器优化介绍: 由于内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问.另外在现代CPU中指令的执行并不一定严格按照顺序执行,没 ...

  7. ROS的使用

    1.输入roscore时出现错误:Unable to contact my own server at 修改: 在.bashrc文件中添加以下内容: export ROS_HOSTNAME=local ...

  8. FATFS模块应用笔记

    FATFS模块应用笔记 如何港 范围 内存使用 模块尺寸缩小 长文件名 统一的API 重入 复制文件访问 性能有效文件访问 对闪存介质考虑 关键的第 延长使用FATFS API 关于FATFS许可证 ...

  9. 监听器、拦截器完成对session、cookie的会话控制

    package com.trsmedia.interceptor; import java.util.Date; import java.util.Timer; import java.util.Ti ...

  10. MySQL的安装配置(无坑

    简单记录一下自己掉坑无数之后,终于找到的一个不坑的方法. 一.安装 #进入一个习惯的文件夹 cd /usr/local/src #下载资源包 wget -i -c http://dev.mysql.c ...