TCP实现并发

#client客户端
import socket client = socket.socket()
client.connect(('127.0.0.1',8080)) while True:
msg = input('>>>:').strip()
if len(msg) == 0:continue
client.send(msg.encode('utf-8'))
data = client.recv(1024)
print(data.decode('utf-8')) #server服务端
import socket
from threading import Thread server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5) def talk(conn):
while True:
try:
data = conn.recv(1024)
if len(data) == 0:break
print(data.decode('utf-8'))
conn.send(data.upper())
except ConnectionResetError as e:
print(e)
break
conn.close() while True:
conn, addr = server.accept() # 监听 等待客户端的连接 阻塞态
print(addr)
t = Thread(target=talk,args=(conn,)) #将连入的客户端带到一个线程中
t.start() #通过创建线程的方式,让线程来“接待”连入的客户端从而达到并发的效果

GIL全局锁解释器

GIL本质就是一把互斥锁:将并发变成串行牺牲效率保证数据的安全。

用来阻止同一个进程下的多个线程的同时执行(同一进程内多个线程无法实现并行但可以实现并发)

CIL的存在是因为Cpython解释器的内存管理,而不是线程安全。

#用代码来验证
from threading import Thread
import time n = 100 def task():
global n
tmp = n
#time.sleep(1) # 如果让程序睡眠一秒(即出现I/O操作,会自动释放锁,导致最后的到的结果是99,这是因为在你释放锁了之后别的子线程也可以抢锁拿到这个数据,然后再进行操作,如果不让程序睡眠(不让程序出现I/O操作的话),那么就和普通的互斥锁一样,谁抢到谁来运行,最后结果是0)
n = tmp-1 t_list = []
for i in range(100):
t = Thread(target=task)
t.start()
t_list.append(t) for t in t_list:
t.join()
print(n)

python多线程是否有用的讨论

因为python的多线程并不能利用多核优势,那么python的多线程是否还有用?

这个需要分情况讨论:

在计算密集型的任务时(比如有4个任务,每个任务是10秒)

单核情况下:

开线程更省资源(因为单核情况下都是并发,开线程的资源明显比开进程的资源少)

多核情况下:

开进程可能是10秒多(多核的情况下,开进程可以达到一个并行的效果,所以4个一起执行的时间相当于每一个的时间),而开线程可能需要40多秒(因为线程只能并发)

#计算密集型
from multiprocessing import Process
from threading import Thread
import os,time
def work():
res=0
for i in range(1000):
res*=i if __name__ == '__main__':
l=[]
print(os.cpu_count()) # 本机为6核
start=time.time()
for i in range(6):
# p=Process(target=work) #耗时 4.732933044433594
p=Thread(target=work) #耗时 22.83087730407715
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print('run time is %s' %(stop-start))
#多核的情况下,计算密集型开进程比开线程快

在I/O密集型的任务时(同样是4个任务)

单核情况下和多核情况下都是开线程更节省资源

因为I/O型的任务需要不停的切换,所以即使是多个进程也需要在阻塞态等待,而开线程明显更节省资源。

#I/O密集型
from multiprocessing import Process
from threading import Thread
import threading
import os,time
def work():
time.sleep(2) if __name__ == '__main__':
l=[]
print(os.cpu_count()) #本机为6核
start=time.time()
for i in range(4000):
p=Process(target=work) #耗时9.001083612442017s多,大部分时间耗费在创建进程上
# p=Thread(target=work) #耗时2.051966667175293s多
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print('run time is %s' %(stop-start))
#I/O密集型的情况下开线程比开进程快

死锁与递归锁

#死锁
from threading import Thread,Lock,current_thread
import time mutexA = Lock()
mutexB = Lock() class MyThread(Thread):
def run(self): # 创建线程自动触发run方法 run方法内调用func1 func2相当于也是自动触发
self.func1()
self.func2() def func1(self):
mutexA.acquire()
print('%s抢到了A锁'%self.name) # self.name等价于current_thread().name
mutexB.acquire()
print('%s抢到了B锁'%self.name)
mutexB.release()
print('%s释放了B锁'%self.name)
mutexA.release()
print('%s释放了A锁'%self.name) def func2(self):
mutexB.acquire()
print('%s抢到了B锁'%self.name)
time.sleep(1)
mutexA.acquire()
print('%s抢到了A锁' % self.name)
mutexA.release()
print('%s释放了A锁' % self.name)
mutexB.release()
print('%s释放了B锁' % self.name) for i in range(10):
t = MyThread()
t.start()
#当出现Thread-1抢到了锁B,Thread-2抢到了锁A的时候,程序卡主,也就是进入了死锁状态,
这是因为Thread-1在执行到func2中的抢锁B时,锁A被Thread-2抢到了,这时Thread-1的下一步是抢锁A,
但被Thread-2已经占住了,而Thread-2下一步要抢的锁B此时被Thread-1占住,谁都进行不了下一步,所以卡住,
于是出现了死锁现象。
#递归锁
from threading import Thread,RLock,current_thread
import time mutexA = mutexB = RLock() class MyThread(Thread):
def run(self):
self.func1()
self.func2() def func1(self):
mutexA.acquire()
print('%s抢到了锁A'%self.name)
mutexB.acquire()
print('%s抢到了锁B'%self.name)
mutexB.release()
print('%s释放了锁B'%self.name)
mutexA.release()
print('%s释放了锁A' % self.name) def func2(self):
mutexB.acquire()
print('%s抢到了锁B'%self.name)
time.sleep(1)
mutexA.acquire()
print('%s抢到了锁A'%self.name)
mutexA.release()
print('%s释放了锁A'%self.name)
mutexB.release()
print('%s释放了锁B' % self.name) for i in range(10):
t = MyThread()
t.start()
#递归锁的意思就是这个锁可以被同一个人多次抢,也就是说当第一个人抢到这个把锁时,
锁的计数会加一,此时别人无法抢这把锁,但这个人还可以再抢这把锁,然后计数继续加一,
只要锁上有计数的时候别人就不能抢这把锁,但释放锁的时候,计数有多少就要释放多少次,
释放完之后别人才可以抢。

信号量

# 信号量可能在不同的领域中 对应不同的知识点
"""
互斥锁:一个厕所(一个坑位)
信号量:公共厕所(多个坑位)
"""
from threading import Semaphore,Thread
import time
import random sm = Semaphore(5) #造了一个含有五个坑位的公共厕所 def task(name):
sm.acquire()
print('%s占了一个坑位'%name)
time.sleep(random.randint(1,3))
sm.release() for i in range(40):
t = Thread(target=task,args=(i,))
t.start()

event事件

from threading import Event,Thread
import time # 先生成一个event对象
e = Event() def light():
print('红灯正亮着')
time.sleep(3)
e.set() #设置event的状态为True,唤醒被阻塞的线程# 发信号
print('绿灯亮了') def car(name):
print('%s正在等红灯'%name)
e.wait() # 设置event的状态为False,阻塞线程# 等待信号
print('%s加油门飙车了'%name) t = Thread(target=light)
t.start() for i in range(10):
t = Thread(target=car,args=('伞兵%s'%i,))
t.start()
#event的作用是,生产一个Event对象,在线程执行到某个阶段的时候我们可以设置一个Event对象,
通过改变event对象的状态来阻塞或者唤醒线程的执行。

线程q(队列)

同一个进程下的多个线程本来就是数据共享,为什么还要用队列,因为队列是管道+锁,使用队列就不需要你来自己手动操作锁的问题,而且锁操作的不好容易产生死锁现象。

import queue
q = queue.Queue() # 先进先出
q.put('hahaha')
q.put('hihihi')
print(q.get()) q = queue.LifoQueue() #后进先出
q.put(1)
q.put(2)
q.put(3)
print(q.get()) q = queue.PriorityQueue()
#put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小(可以是负的)优先级越高
q.put((10,'haha'))
q.put((100,'hehehe'))
q.put((0,'xxx'))
q.put((-10,'yyy'))
print(q.get())

TCP并发、GIL、锁的更多相关文章

  1. 并发编程-多线程,GIL锁

    本章内容: 1.什么是GIL 2.GIL带来的问题 3.为什么需要GIL 4.关于GIL的性能讨论 5.自定义的线程互斥锁与GIL的区别 6.线程池与进程池 7.同步异步,阻塞非阻塞 一.什么是GIL ...

  2. 多道技术 进程 线程 协程 GIL锁 同步异步 高并发的解决方案 生产者消费者模型

    本文基本内容 多道技术 进程 线程 协程 并发 多线程 多进程 线程池 进程池 GIL锁 互斥锁 网络IO 同步 异步等 实现高并发的几种方式 协程:单线程实现并发 一 多道技术 产生背景 所有程序串 ...

  3. 53_并发编程-线程-GIL锁

    一.GIL - 全局解释器锁   有了GIL的存在,同一时刻同一进程中只有一个线程被执行:由于线程不能使用cpu多核,可以开多个进程实现线程的并发,因为每个进程都会含有一个线程,每个进程都有自己的GI ...

  4. 操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁

    并发编程前言: 1.网络应用 1)爬虫 直接应用并发编程: 2)网络框架 django flask tornado 源码-并发编程 3)socketserver 源码-并发编程 2.运维领域 1)自动 ...

  5. 并发,并行,线程,进程,GIL锁

    1.并发和并行 并发: 同时做某些事,但是强调同一时段做多件事 如:同一路口,发生了车辆要同时通过路面的时间. 并行: 互不干扰的在同一时刻做多件事 如:同一时刻,同时有多辆车在多条车道上跑,即同时发 ...

  6. 并发编程: GIL锁、GIL与互斥锁区别、进程池与线程池的区别

    一.GIL 二.关于GIL性能的讨论 三.计算密集测试 四.IO密集测试 五.GIL与互斥锁 六.TCP客户端 七.进程池 八.进程什么时候算是空闲 九.线程池 一.GIL GIL Global In ...

  7. python并发编程-多线程实现服务端并发-GIL全局解释器锁-验证python多线程是否有用-死锁-递归锁-信号量-Event事件-线程结合队列-03

    目录 结合多线程实现服务端并发(不用socketserver模块) 服务端代码 客户端代码 CIL全局解释器锁****** 可能被问到的两个判断 与普通互斥锁的区别 验证python的多线程是否有用需 ...

  8. Python并发编程05 /死锁现象、递归锁、信号量、GIL锁、计算密集型/IO密集型效率验证、进程池/线程池

    Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密集型效率验证.进程池/线程池 目录 Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密 ...

  9. [并发编程 - 多线程:信号量、死锁与递归锁、时间Event、定时器Timer、线程队列、GIL锁]

    [并发编程 - 多线程:信号量.死锁与递归锁.时间Event.定时器Timer.线程队列.GIL锁] 信号量 信号量Semaphore:管理一个内置的计数器 每当调用acquire()时内置计数器-1 ...

  10. python并发编程之线程(创建线程,锁(死锁现象,递归锁),GIL锁)

    什么是线程 进程:资源分配单位 线程:cpu执行单位(实体),每一个py文件中就是一个进程,一个进程中至少有一个线程 线程的两种创建方式: 一 from threading import Thread ...

随机推荐

  1. 目录服务不能与此服务器复制,因为距上一次与此服务器复制的时间已经超过了 tombstone 生存时间。

    1.PDC数据正常 2.其他DC无法复制,报如下错误:目录服务不能与此服务器复制,因为距上一次与此服务器复制的时间已经超过了 tombstone 生存时间. 3.直接强制复制即可 repadmin / ...

  2. java 继承条件下的构造方法调用

    运行 TestInherits.java示例,观察输出,注意总结父类与子类之间构造方法的调用关系修改Parent构造方法的代码,显式调用GrandParent的另一个构造函数,注意这句调用代码是否是第 ...

  3. 使用log4cxx

    在java中有log4j日志模块,使用起来非常方便,在C++中也是有的,log4cxx就是log4j的c++移植版,机缘巧合之下今天想要使用一下这个日志模块,所以记录下自己从一开始下载安装到成功使用的 ...

  4. javaweb05 文件的上传一

    2.使用fileupload组件完成文件的上传应用 1).需求: I. 上传 >在upload.jsp页面上使用jQuery实现"新增一个附件","删除附件&quo ...

  5. keras_yolo3阅读

    源码地址 https://github.com/qqwweee/keras-yolo3 春节期间仔细看了看yolov3的kears源码,这个源码毕竟不是作者写的,有点寒酸,可能大道至简也是这么个理.我 ...

  6. JavaScript—封装animte动画函数

    封装Animte 动画函数 虽然可能以后的开发中可能根本不需要自己写,Jquery 给我们封装好了,或者用CSS3的一些属性达到这样的效果可能更简单. 我比较喜欢底层的算法实现,万变不离其中,这个逻辑 ...

  7. html_js_jq_css

    // ----- JQ $(function(){$(div').bind('mouseout mouseover', function () {// 移入和移出分别执行一次alert('bind 可 ...

  8. 熟练使用WebApi开发

    在建立WebApi框架的时候,要想自己的业务需求是什么.例如PC端(前端),APP端都要使用的同一接口,就得考虑Webapi来提供接口支持了.最近公司刚好让我整合一下公司的接口项目(有WebServi ...

  9. 配对t检验

  10. Linux-proc文件系统介绍

    1.操作系统级别的调试 (1).简单程序单步调试 (2).复杂程序printf打印信息调试 (3).框架体系日志记录信息调试 (4).内核调试的困境 2.proc虚拟文件系统的工作原理 (1).Lin ...