一、死锁与递归锁(了解)

1 死锁

程序中如果出现多个锁操作容易造成死锁现象

from threading import Thread,Lock

import time
# 实例化两个锁对象
a = Lock()
b = Lock() class MyThread(Thread):
def run(self):
self.func1()
self.func2() def func1(self):
a.acquire() # 10个线程去抢和这个锁
print(self.name)
b.acquire() # 抢到a的才能抢b
print(self.name)
b.release()
a.release() # 施放a的时候 线程2瞬间抢到了a开始执行 def func2(self):
b.acquire() # 线程1抢到b和线程2互相卡死,因为需要对方的锁才能施放自己的锁
print(self.name)
time.sleep(2)
a.acquire()
print(self.name)
a.release()
b.release() for i in range(10):
t = MyThread()
t.start()

2 递归锁

"""
递归锁的特点
可以被连续的acquire和release
但是只能被第一个抢到这把锁执行上述操作
它的内部有一个计数器 每acquire一次计数加一 每realse一次计数减一
只要计数不为0 那么其他人都无法抢到该锁
"""
# 将上述的
mutexA = Lock()
mutexB = Lock()
# 换成
mutexA = mutexB = RLock()

二、信息量

信号量在不同的阶段可能对应不同的技术点

在并发编程中信号量指的是锁

from threading import Thread, Semaphore
import time
import random sm = Semaphore(5) # 括号内写数字 写几就表示开设几个坑位
# 内置方法和锁一样,抢和施放
# 区别在于信号量可以规定一次性抢锁的最大数量 def task(name):
sm.acquire()
print('%s 正在蹲坑'% name)
time.sleep(random.randint(1, 5))
sm.release() if __name__ == '__main__':
for i in range(20):
t = Thread(target=task, args=('伞兵%s号'%i, ))
t.start()

三、Event事件

一些进程或者线程遇到等待另外一些进程或者线程运行完毕之后才能运行,类似发射信号

from threading import Thread, Event
import time event = Event() # 造了一个红绿灯 def light():
print('红灯亮着的')
time.sleep(3)
print('绿灯亮了')
# 告诉等待红灯的人可以走了
event.set() def car(name):
print('%s 车正在灯红灯'%name)
event.wait() # 等待别人给你发信号
print('%s 车加油门飙车走了'%name) if __name__ == '__main__':
t = Thread(target=light)
t.start() for i in range(20):
t = Thread(target=car, args=('%s'%i, ))
t.start()

四、三种优先级数据操作

同一个进程下多个线程数据共享,但为了保证数据安全,我们需要用到以下三种数据操作

1 队列

原则:先进先出

import queue

q = queue.Queue(3)

q.put(1)
q.put(2)
q.put(3) print(q.empty()) # 判断队列是否为空
print(q.full()) # 判断队列是否为满 q.get()
q.get()
q.get()
q.get(timeout=3) # 等待3秒再取数据,如果没有就报错
q.get_nowait() # 不等待,没有数据就报错

2 堆栈

原则:先进后出

堆栈
import queue q = queue.LifoQueue(3) # last in first out q.put(1)
q.put(2)
q.put(3) print(q.get())
>>> 3

3 自定义优先级

import queue

q = queue.PriorityQueue(3) # 上传数据时要先上传一个该数字排名,排名小的现出来

q.put(('5',1))
q.put(('0',1))
q.put(('-1',1)) print(q.get_nowait())
>>> ('-1',1)

五、进程池和线程池

之前在tcp实现并发的时候我们是来一个用户就启用一个线程或者进程去为用户服务
但是计算机的硬件资源目前还无法支持我们无限制的开发线程
所以用到了池的概念
池相当于缓冲地带,让我们可以保证计算机在正常运行的情况下最大限度的利用它
它降低了程序的运行效率,但是保证了计算机的安全 如果把计算机比喻成一个小池子你限定了池子最大容量是1,你要喂食,池子就会先产生一条鱼,给你喂,其他人想喂就得等你结束,过来喂的是同一条鱼 而如果不用池的概念去限定,每个人来池子都会给人产生一条鱼来服务,鱼多了,池子就炸了。

基本使用

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import time
import os # pool = ThreadPoolExecutor(5)# 线程池里只有5个线程
pool = ProcessPoolExecutor(2)# 进程池里只有5个进程
# 括号内可以传数字 不传的话默认会开设当前计算机cpu个数五倍的线程
# 池子造出来之后 里面会固定存在五个线程
# 这个五个线程不会出现重复创建和销毁的过程
# 池子的使用非常的简单
# 你只需要将需要做的任务往池子中提交即可 自动会有人来服务你 def text(n):
print(os.getpid())
time.sleep(3)
return n**n def callback(n):
print(n.result()) if __name__ == '__main__':
res = pool.submit(text,2) # 返回值是一个对象 # print('主') # 异步提交,判断异步的方式,在任务提交后得到返回值之前能不能执行代码 # print(res.result()) # 得到的是提交任务的返回值 t_list = []
for i in range(10):
pool.submit(text,i).add_done_callback(callback) # 自定义异步回调机制,在任务得到返回值的时候直接调用里面的函数
# 这种回调机制可以想象为,在提交任务后,直接运行下面的代码,什么时候有返回值了,会立刻调用该方法,相当于埋下了定时炸弹,返回值来了就触发
# res = pool.submit(text,i).result() # 这种得到结果的方式是同步
# t_list.append(res)
# pool.shutdown() # 关闭所有线程
# for i in t_list:
# print(i)

六、协程

  • 进程:资源单位
  • 线程:执行单位
  • 协程:意淫出来的
    • 为了在多线程实现并发,我们在多线程中出现io情况都切换走,去执行其他线程,这样就会让计算机看起来一直在运行没有中断过。从而提升了程序的运行效率

七、gevent模块

from gevent import monkey;monkey.patch_all()
# 猴子补丁,用来检测程序里出现的io操作
import time
from gevent import spawn def a():
print('a')
time.sleep(2)
print('a end') def b():
print('b')
time.sleep(4)
print('b end') start = time.time()
g1 = spawn(a)
g2 = spawn(b)
g1.join()
g2.join()# 等待任务执行完再执行后面的代码
print(time.time()-start) # 4.015194654464722 实现了io时间切换操作,用户只需等待最长的任务时间

八、协程实现tcp并发

#服务端
import socket
from gevent import monkey;monkey.patch_all()
from gevent import spawn def communication(conn):
while True:
try:
msg = conn.recv(1024)
if len(msg) == 0:break
conn.send(msg.upper())
except Exception as e:
print(e)
break
conn.close() def sever(ip,port):
s = socket.socket()
s.bind((ip, port))
s.listen(5)
while True:
conn,addr = s.accept()
communication(conn) if __name__ == '__main__':
g = spawn(sever,'127.0.0.1',8080)
g.join() # 客户端 import socket
from threading import Thread,current_thread def client():
s = socket.socket()
s.connect(('127.0.0.1', 8080))
n = 0
while True:
msg = '%s say hello %s' % (current_thread().name, n)
n += 1
s.send(msg.encode('utf-8'))
data = s.recv(1024)
print(data.decode('utf-8')) if __name__ == '__main__':
for i in range(50):
t = Thread(target=client)
t.start()

day41 几个琐碎知识点的更多相关文章

  1. Java琐碎知识点

    jps命令是JDK1.5提供的一条显示当前用户的所有java进程pid的指令,类似Linux上的ps命令简化版,Windows和linux/unix平台都可以用比较常用的参数:-q:只显示pid,不显 ...

  2. linux琐碎知识点

    1.awk的使用方式,pattern支持正则表达式 awk 'pattern{action}' {filenames} 其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找 ...

  3. linux学习之一些琐碎知识点

    一.python 问:django中project和app之间到底有什么不同? 答:他们的区别就是一个是配置,另一个是代码. 一个project包含很多个django app以及对它们的配置.技术上, ...

  4. Java知识点:琐碎知识点(3)

    零碎 switch(x),x只可以是enum或byte.short.char.int. 枚举在switch-case语句作为标签时必须是枚举常量的非限定名称,否则Compile Error. Enum ...

  5. Java知识点:琐碎知识点(2)

    49个关键字一览 abstract default if private this boolean do implements protected throw break double import ...

  6. Java知识点:琐碎知识点(1)

    Java基本介绍 SUN:Stanford University NetworkJava之父:James GoslingJava的跨平台性因为有Java虚拟机,运行class文件.Java吉祥物:Du ...

  7. ROS机器人编程实践----琐碎知识点

    amcl原理: amcl将激光传感器数据与从地图预估的传感器数据相比较,给出可能的位姿.如果传感器数据和某个候选位姿处的预测数据相同,amcl就会给这个位姿一个较高的概率,反之,就会降低这个概率.概率 ...

  8. CSS琐碎知识点(持续补充)

    一.字体单位,pt?px?em?rem? pt:磅,一种固定长度的绝对的度量单位,是能够使用测量设备测得的长度,印刷业上经常使用,一般用于页面打印排版. px:屏幕设备上能显示出的最小的一个物理点,这 ...

  9. HTML琐碎知识点(持续补充)

    一.table标签 <table> <thead> <tr> <th>111</th> </tr> </thead> ...

随机推荐

  1. jdbc+mysql常见报错总结

    1.The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You ...

  2. 利用Python将多个PDF文件合并

    from PyPDF2 import PdfFileMerger import os files = os.listdir()#列出目录中的所有文件 merger = PdfFileMerger() ...

  3. jQuery - Ajax ajax方法详解

    $.ajax()方法详解 jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Strin ...

  4. MyBatis使用模糊查询用户信息及log4j配置文件详解

    1.1 根据用户名称模糊查询用户信息 根据用户名模糊查询用户信息,只需要我们更改映射文件中的sql语句.其他的内容跟上一篇的内容是一样的 1.2添加根据用户名称模糊查询用户信息的sql语句 实例中是查 ...

  5. Linux基础:pkill命令总结

    本文只总结一些常用的用法,更详细的说明见man pkill和pkill --help. pkill命令 pkill命令:通过进程名杀死进程. 语法格式 Usage: pkill [options] & ...

  6. 从零开始的Spring Boot(3、Spring Boot静态资源和文件上传)

    Spring Boot静态资源和文件上传 写在前面 从零开始的Spring Boot(2.在Spring Boot中整合Servlet.Filter.Listener的方式) https://www. ...

  7. mybatis配置和使用

    1,配置 MyBatis实现映射器的2种方式:XML文件形式和注解形式,下文主要是用xml形式,比较好维护 mybatis-config.xml文件: <?xml version="1 ...

  8. mysql explain的type的

    导语 很多情况下,有很多人用各种select语句查询到了他们想要的数据后,往往便以为工作圆满结束了.这些事情往往发生在一些学生亦或刚入职场但之前又没有很好数据库基础的小白身上,但所谓闻道有先后,只要我 ...

  9. [apue] 一个快速确定新系统上各类限制值的工具

    对于在不同 Unix 系统之间移植程序,最重要的事情就是确定新系统的一些编译时.运行时固定或不固定的限制值了.例如文件路径最大长度 PATH_MAX.进程最大可打开文件句柄数 OPEN_MAX.用户可 ...

  10. Beta冲刺<10/10>

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺--第十天(05.28) 作业正文 如下 其他参考文献 ... B ...