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)

  

最新文章

  1. javascript的 Object 和 Function
  2. [POJ3111]K Best(分数规划, 二分)
  3. IOS开发之GCD---dispatch_semaphore
  4. [CF#290 Div.1 C]Fox And Dinner(最大流)
  5. Euclidean Space
  6. BZOJ 1057: [ZJOI2007]棋盘制作
  7. 微软职位内部推荐-SW Engineer II for Skype
  8. MVC session过期如何处理跳转
  9. aix 文件大小相关查询
  10. 使用Eclipse EE开发web项目
  11. Angularjs 基于karma和jasmine的单元测试
  12. HDU 1484 Basic wall maze (dfs + 记忆)
  13. 提升单元测试体验的利器--Mockito使用总结
  14. easyui增删改查前段代码
  15. Java EE 8 来了
  16. VR/AR 科技了解
  17. hive支持sql大全(收藏版)
  18. AtCoder Grand Contest 004
  19. PostgreSQL CPU满(100%)性能分析及优化
  20. javascript设计模式系列二-封装

热门文章

  1. Oracle单表备份三种方案
  2. gym/102253C Colorful Tree 树上计数
  3. 第4篇创建harbor私有镜像库
  4. 力扣—— Swap Nodes in Pairs(两两交换链表中的节点) python实现
  5. 【串线篇】SpringMvc视图解析
  6. git 初始化提交项目
  7. PHP上传文件和下载
  8. C语言结构体实例-创建兔子
  9. Tomcat6 只允许指定域名访问,禁用IP地址访问,防止恶意解析
  10. Migrating Your Android App from Eclipse to Android Studio