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. 聚类算法总结以及python代码实现

    一.聚类(无监督)的目标 使同一类对象的相似度尽可能地大:不同类对象之间的相似度尽可能地小. 二.层次聚类 层次聚类算法实际上分为两类:自上而下或自下而上.自下而上的算法在一开始就将每个数据点视为一个 ...

  2. share团队冲刺6

    团队冲刺第六天 昨天:进行各种原件的自定义样式,进行界面布局 登陆界面: 今天:进行后台的代码编写,实现各种按钮的功能 问题:在不同的型号手机上,界面会发生不兼容的问题.

  3. hdu1066 Last non-zero Digit in N!(求阶乘最后一位不为0的数字)

    http://acm.hdu.edu.cn/showproblem.php?pid=1066 转自:https://blog.csdn.net/fengyu0556/article/details/5 ...

  4. chrome安装switchyomega

    由于在国外网站找不到下载链接,在国内招了个crx文件,以下为安装crx教程 首先修改后缀为zip,再解压, 得到以下文件 然后在chrome里找到扩展程序, 打开开发者模式,点击-加载已解压的扩展程序 ...

  5. 绩效软件交流-ZQDJ

    积分制(主管激励下属)短期任务积分 长期任务积分 制度积分 固定积分任务工作项 评估表 ,取中间值工时调整 工作表现 创新加分 难度加分 贡献加分 绩效分-积分(软件亮点)  分开做 没有管理员的中层 ...

  6. python编程:从入门到实践----第六章:字典>练习

    6-1 人:使用一个字典来存储一个熟人的信息,包括名.姓.年龄和居住的城市.该字典应包含键first_name .last_name .age 和city .将存储在该字典中的每项信息都打印出来. f ...

  7. numpy(一)

    ndarray np的一个核心类,它描述了相同类型的“项目”集合.可以使用例如N个整数来索引项目.每个项目占用相同大小的内存块, 并且所有块都以完全相同的方式解释. 如何解释数组中的每个项目由单独的数 ...

  8. long型长整数字在前端页面显示异常及其解决方法

    文章目录 1.引子 2.解决问题 (1)初试EL表达式取long型数值 (2)再探EL表达式取字符串格式long型数值 (3)最后一试---给EL表达式加引号 3.总结 1.引子 在做项目中,发现了一 ...

  9. winEdt打开tex文件报错解决方法

    写论文真的是不断遇到各种困难啊,这个Latex软件就很多,好不容易中个A1区的文章,期刊说更新了新的模板就下载了,忽然发现打开有reading error,看不到一点内容,神奇的是竟然可以运行.这样的 ...

  10. 如何选字体(font-family)

    一.默认字体情况 1.Window下: 宋体(SimSun):Win下大部分游览器的默认字体,宋体在小字号下(如12px.14px)的显示效果还可以接受,但是字号一大就非常糟糕了,所以使用的时候要注意 ...