线程同步互斥方法(二)
1、条件变量 condition
1、创建条件变量对象
con = threading.Condition()2、条件变量对象的方法
1、con.acquier()
功能:对资源加锁,加锁后其他位置再加锁则堵塞
2、con.release()
功能:解锁
3、con.wait()
要求:wait函数只能在加锁的状态下使用
功能:
wait函数会先解锁(release),然后让线程处于等待通知的阻塞状态
4、con.notify()
功能:发送通知,线程接收到通知后结束wait堵塞,并且执行 acquire 加锁操作
示例:
import threading as td
import time
import datetime as dtime
num = 0
# 条件变量
con = td.Condition()
class Gov(td.Thread):
def run(self):
global num
con.acquire()
while True:
print('开始拉升股市')
num += 1
print('拉升了%d个点' % num)
time.sleep(2)
if num == 5:
print('暂时安全')
con.notify()
print('不操作状态')
con.wait()
con.release()
class Consumers(td.Thread):
def run(self):
global num
con.acquire()
while True:
if num > 0:
print('开始打压股市')
num -= 1
print('下降了%d个点' % num)
time.sleep(2)
if num == 0:
print('天才在哪')
con.notify()
print('不能再下降了')
con.wait()
con.release()
t1 = Gov()
t2 = Consumers()
t1.start()
t2.start()
2、线程池
Threadpool 第三方模块3、Python线程值GIL(全局解释器锁)
Python--->支持多线程--->同步互斥--->加锁--->超级锁--->在同一时刻,解释器只能解释一个线程--->大量Python库为了省事沿用了这种方法--->Python多线程效率低下
GIL问题:
由于Python的全局解释器锁造成Python的多线程效率低下解决方法:
1、不使用线程,使用多进程2、不使用C C++ 做解释器 C# Java也可以做Python解释器
3、Python线程适合高用时的IO操作,如网络IO。不适合CPU密集型程序
4、设计模式
设计模式代表了一种最佳实践,是被开发人员长期总结,用来解决某一类问题的思路方法。这些方法保证了代码的效率也易于理解
设计模式示例:单例模式 工厂模式 生产者模式 ……
生产者消费者模式:
作用:
控制数据资源数量
降低耦合度
多个消费者 消耗
多个生产者 生产
均对仓库资源进行操作
from threading import Thread
# python标准库队列
import queue
import time
# 创建一个队列作为仓库
q = queue.Queue()
# 生产者
class Producer(Thread):
def run(self):
count = 0
while True:
if q.qsize() < 50:
for i in range(3):
count += 1
msg = '产品 %d' % count
q.put(msg) # 将产品放入队列
time.sleep(1)
class Customes(Thread):
def run(self):
while True:
if q.qsize() > 20:
for i in range(2):
msg = q.get() # 从仓库拿货
print('消费了%s' % msg,'还有%d个'%q.qsize())
time.sleep(1)
for i in range(2):
p = Producer()
p.start()
for i in range(3):
c = Customes()
c.start()
总结:
1、进程线程区别和联系
2、同步互斥的意义和实现方法
3、进程线程使用什么样的方式通信
4、进程线程的特点和选择
5、简单的设计模式的理解
6、僵尸进程,进程状态,GIL等概念的理解
5、服务器模型
1、服务器基本介绍
硬件服务器: 主机 集群生产服务器厂家:IBM HP
软件服务器:
网络服务器 在后端提供网络功能,逻辑处理,数据处理的程序或者架构等
如:httpserver django flask
服务器架构:
c/s(客户端服务器架构) b/s(浏览器服务器架构,处理网页) 服务器的组织形式
服务器追求:
处理速度快,数据更安全并发量更大
优化:
硬件:更高配置,更多主机,集成,分布
软件:程序占有更少的资源,更流畅的运行,处理更多的并发
2、基本的服务器模型:
1、处理并发方案:
循环 并发模式 IO多路复用2、循环:
原理:单线程程序,循环接收链接或者请求,然后处理,处理后继续循环
缺点:
不能同时处理多个客户端的并行,不循序某个客户端长期占有服务器
特点:
结构比较简单,适用于udp程序,要求处理请求可以很快完成
3、IO多路复用模型:
原理:通过同时监控多个IO来达到并发的目的
缺点:
也是单线程,不能够长期阻塞,不适合处理大量CPU占有高的程序。
特点:
开销小,比较适合IO密集型的服务端程序。
4、并行服务器
原理:每有一个客户端连接请求,就创建一个新的进程或者线程处理客户端的请求,
而主进程/线程可以继续接收其他客户端的链接
优点:
适合客户端需要长期占有服务器的情况
缺点:
资源消耗较大
3、基于fork的多进程并发
1、创建套接字,绑定,监听2、接收客户端请求
3、创建子进程处理客户端请求,父进程继续准备接收新的客户端连接
4、客户端退出则销毁相应的子进程
示例:
import socket as so
import os
import sys
import signal
# 创建套接字
HOST = ''
PORT = 8888
def client_handler(c):
try:
print('子进程接收{}客户端请求'.format(c.getpeername()))
while True:
data = c.recv(1024).decode()
if not data:
break
print(c.getpeername(), '>>> ', data)
c.send(b'receive your message')
except(KeyboardInterrupt, SystemExit):
raise
except Exception as e:
print(e)
c.close()
sys.exit(0) # 结束子进程
s = so.socket()
s.setsockopt(so.SOL_SOCKET, so.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(5)
print('父进程%d等待客户端连接' % os.getpid())
while True:
try:
c, addr = s.accept()
except KeyboardInterrupt:
raise
except Exception as e:
print(e)
continue
# 为新的客户端创建进程
# 处理僵尸进程
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
pid = os.fork()
if pid < 0:
print('创建子进程失败')
c.close()
continue
elif pid == 0:
s.close()
# 处理客户端请求
client_handler(c)
else:
c.close()
continue
4、TFTP文件服务器
文件的上传下载和文件服务的文件库的查看服务端 客户端
查看文件库中有那些文件
下载文件到本地
讲本地文件上传到文件库
确定技术:
fork ---多进程
tcp socket
*_*cookie
os.listdir(path)
功能:
获取文件夹下所有的文件列表,形成一个列表
os.path.isfile(path)
判断一个文件是否是普通文件
os.path.isdir(path)
判断一个文件是否是文件夹
tftp_server.py
tftp_client.py