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 354B 博弈, DP,记忆化搜索

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

  2. Android开发中怎样用多进程、用多进程的好处、多进程的缺陷、解决方法(转)

    转自:http://blog.csdn.net/spencer_hale/article/details/54968092 1.怎样用多进程 Android多进程概念:一般情况下,一个应用程序就是一个 ...

  3. 一次CTS引发的网络故障

    接到业务部门通知,A机房(库a)到B机房(库b)之间的数据库服务器之间的网络带宽异常突增,影响公司对外业务的整体带宽.一接到通知,作为数据库管理对所涉及的IP还是比较敏感.第一反应就是可能当时主库产生 ...

  4. 【串线篇】SQL映射文件delete/ insert/ update标签

    一. <insert id="insertEmployee"> INSERT INTO t_employee(empname,gender,email) VALUES( ...

  5. vue 之组件

    组件 '''1.根组件:new Vue()创建的组件,一般不明确自身的模板,模板就采用挂载点2.局部组件: local_component = {}2.全局组件: Vue.component({})' ...

  6. 常见算法和数据结构存在的坑(updating)

    数组: c++数组下标都+5会稳. 50005000的别开60006000. 二分: 实数二分可能因为神马精度问题出现了不满足二分序的情况,要小心. 注意二分完后,不能直接用当前数组里存的值,要pd( ...

  7. PHP curl_pause函数

    curl_pause — 暂停及恢复连接. 说明 int curl_pause ( resource $ch , int $bitmask ) 参数 ch 由 curl_init() 返回的 cURL ...

  8. Python基础教程(011)--程序开发中的错误及原因

    前言 排查代码开发中的错误 内容 1,编写的程序不能正常执行,或者执行的结果不是我们期望的 2,俗称bug,是程序开发常见的,初学常见的原因有 手误 对已经学习的知识点理解不足 对语音还有需要学习和提 ...

  9. LG1010 幂次方

    题目描述 任何一个正整数都可以用2的幂次方表示.例如 137=2^7+2^3+2^0 同时约定方次用括号来表示,即a^b 可表示为a(b). 由此可知,137可表示为: 2(7)+2(3)+2(0) ...

  10. JDK各个版本比较

    JDK5 自动装箱与拆箱: 枚举 静态导入,如:import staticjava.lang.System.out 可变参数(Varargs) 内省(Introspector) 主要用于操作JavaB ...