线程通信

通信方法:多个线程共用进程空间,所以进程的全局变量对进程内线程均可见。线程往往使用全局变量进行通信

注意事项:线程间使用全局变量进行通信,全局变量为共享资源,往往需要同步互斥机制

线程的同步互斥

线程Event

e = threading.Event()  创建事件对象

e.wait([timeout])  事件阻塞函数

e.set()  设置事件
e.clear()  清除事件

 from threading import Thread
 from time import sleep 

 a = 1

 def foo():
     global a
     a = 1000

 def bar():
     sleep(1)
     print("a = ",a)

 t1 = Thread(target = foo)
 t2 = Thread(target = bar)

 t1.start()
 t2.start()

 t1.join()
 t2.join()

 # a =  1000

thread_global

 import threading
 from time import sleep 

 s = None    #共享资源

 e = threading.Event()   #创建事件对象

 def bar():
     print("呼叫foo")
     global s
     s = "天王盖地虎"

 def foo():
     print("等口令")
     sleep(2)
     if s == "天王盖地虎":
         print("宝塔镇河妖")
     else:
         print("打死他")
     e.set() # 设置事件

 def fun():
     print("呵呵....")
     sleep(1)
     e.wait()    # 事件阻塞函数
     global s
     s = "小鸡炖蘑菇"

 b = threading.Thread(target = bar)  # 创建事件对象
 f = threading.Thread(target = foo)
 t = threading.Thread(target = fun)

 b.start()
 f.start()
 t.start()

 b.join()
 f.join()
 t.join()

 # 呼叫foo
 # 等口令
 # 呵呵....
 # 宝塔镇河妖

e = threading.Event()

线程锁 Lock

lock = threading.Lock() 创建锁对象
lock.acquire() 上锁
lock.release() 解锁

with lock 上锁

 import threading 

 a = b = 0 

 lock = threading.Lock()    # 创建锁对象

 def value():
     while True:
         lock.acquire()    # 上锁
         if a != b:
             print("a = %d,b = %d"%(a,b))
         lock.release()    # 解锁

 t = threading.Thread(target = value)    # 创建线程对象
 t.start()

 while True:
     lock.acquire()    # 上锁
     a += 1
     b += 1
     lock.release()    # 解锁

 t.join()

lock.acquire()

python线程的GIL问题

GIL (全局解释器锁)

python ---》 支持线程操作 ---》IO的同步和互斥 --》 加锁 ----》 超级锁,给解释器加锁

后果:一个解释器,同一时刻只解释一个线程,此时其他线程需要等待。大大降低了python线程的执行效率

python GIL问题解决方案
* 修改c解释器
* 尽量使用多进程进行并行操作
* python线程可以用在高延迟多阻塞的IO情形
* 不使用cpython  c# java做解释器

效率测试

分别测试 多进程 多线程 单进程执行相同的IO操作和CPU

 #计算密集
 def count(x,y):
     c = 0
     while c < 7000000:
         x += 1
         y += 1
         c += 1

 #io密集
 def write():
     f = open("test.txt",'w')
     for x in range(2000000):
         f.write("hello world\n")
     f.close()

 def read():
     f = open("test.txt")
     lines = f.readlines()
     f.close()

操作的时间

 #单进程程序
 from test import *
 import time 

 # t = time.time()
 # for i in range(10):
 #     count(1,1)
 # print("Line cpu:",time.time() - t)

 t = time.time()
 for i in range(10):
     write()
     read()
 print("Line IO:",time.time() - t)

Line cpu: 8.15166711807251
Line IO: 6.841825246810913

 from test import *
 import threading
 import time 

 counts = []

 t = time.time()

 for x in range(10):
     th = threading.Thread(target = count,args = (1,1))
     th.start()
     counts.append(th)

 for i in counts:
     i.join()
 print("Thread cpu",time.time() - t)
 from test import *
 import threading
 import time 

 counts = []

 def io():
     write()
     read()

 t = time.time()

 for x in range(10):
     th = threading.Thread(target = io)
     th.start()
     counts.append(th)

 for i in counts:
     i.join()
 print("Thread IO",time.time() - t)

Thread cpu 8.414522647857666
Thread IO 6.023292541503906

 from test import *
 import multiprocessing
 import time 

 counts = []

 t = time.time()

 for x in range(10):
     th = multiprocessing.Process\
     (target = count,args = (1,1))
     th.start()
     counts.append(th)

 for i in counts:
     i.join()
 print("Process cpu",time.time() - t)
 from test import *
 import multiprocessing
 import time 

 counts = []

 def io():
     write()
     read()

 t = time.time()

 for x in range(10):
     th = multiprocessing.Process(target = io)
     th.start()
     counts.append(th)

 for i in counts:
     i.join()
 print("Process IO",time.time() - t)

Process cpu 4.079084157943726
Process IO 3.2132551670074463

进程和线程的区别和联系

1.两者都是多任务编程的方式,都能够使用计算机的多核
2.进程的创建删除要比线程消耗更多的计算机资源
3.进程空间独立,数据安全性好,有专门的进程间通信方法
4.线程使用全局变量通信,更加简单,但是需要同步互斥操 作
5. 一个进程可以包含多个线程,线程共享进程的空间资源
6. 进程线程都独立执行,有自己的特有资源如属性,id, 命令集等

使用情况:
* 一个进程中并发任务比较多,比较简单,适合使用多线程
* 如果数据程序比较复杂,特别是可能多个任务通信比较多 的时候,要考虑到使用线程同步互斥的复杂性
* 多个任务存在明显差异,和功能分离的时候没有必要一定 写入到一个进程中
* 使用python考虑线程GIL问题

要求:
1. 进程线程的区别和关系
2. 进程间都信方式都用过哪些,有什么特点
3. 同步和互斥是怎么回事,你都用哪些方法实现了同步互斥
4. 什么是僵尸进程,怎么处理的
5. python线程的效率怎么样?GIL是怎么处理的

服务器模型

硬件服务器 : 主机 集群
厂商 : IBM HP 联想 浪潮

软件服务器 :编写的服务端程序,依托硬件服务器运行。 提供给用户一定的功能服务

服务器种类

webserver ---》 网络的后端应用程序,提供数据处理和逻辑处理
httpserver ---> 接受http请求,返回http响应

邮箱服务器 ---》 处理邮件请求,进行邮件收发

文件服务器 --》提供文件的上传下载存储

功能实现 : 网络连接,逻辑处理,数据运算,数据交互
协议实现,网络数据传输。。。。

模型结构 : C/S 客户端服务器模型
B/S 浏览器服务器模型

服务器目标:处理速度更快,数据安全性更强,并发量更高

硬件 : 更高的配置,更好的硬件搭配,更高的网络速度
更多的主机,网络安全投入

软件:占有更少的计算机资源,更稳定的运行效率,更流畅的速度,更强大的算法,更合理的技术搭配

网络服务器基础

循环服务器 : 单进程程序,循环接受客户请求,处理请求。处理完毕再接受下一个请求。

特点 : 每次只能处理一个客户端请求;如果客户端长期占有服务器则无法处理其他客户端请求。

优点 : 实现简单,占用资源少
缺点 : 无法同时处理多客户端,体验差
使用情况 : 任务短暂,可以快速完成。udp比tcp更适合循 环

并发服务器 : 能够同时处理多个客户端任务请求

IO 并发 : IO多路复用    协程
优点 : 可以实现IO的并发操作,占用系统资源少
缺点 : 不能监控cpu密集的情况,并能有长期阻塞

多进程/多线程并发:为每个客户端单独提供一个进程/ 线程处理客户端请求

优点 : 客户端可以长期占有服务器
缺点 : 消耗计算机资源较多

多进程并发模型

使用fork完成并发

1. 创建套接字,绑定,监听
2. 等待接受客户端连接请求
3. 创建新的进程处理客户端请求,父进程继续等待连接其他客户端
4. 客户端退出,对应子进程结束

 from socket import *
 import os,signal,sys,time  

 FILE_PATH = "/home/tarena/"    #文件库
 class TftpServer(object):    #实现功能模块
     pass 

 #流程控制,创建套接字,创建并发,方法调用
 def main():
     HOST = '0.0.0.0'
     PORT = 8888
     ADDR = (HOST,PORT)

     sockfd = socket()
     sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
     sockfd.bind(ADDR)
     sockfd.listen(5)

     signal.signal(signal.SIGCHLD,signal.SIG_IGN)

     while True:
         try:
             connfd,addr = sockfd.accept()
         except KeyboardInterrupt:
             sockfd.close()
             sys.exit("服务器退出")
         except Exception as e:
             print(e)
             continue
         print("客户端登录:",addr)

         #创建父子进程
         pid = os.fork()    # 子进程处理客户端请求,父进程等待其他客户端连接

         if pid == 0:
             sockfd.close()
             tftp = TftpServer()  # __init__传参
             while True:
                 data = connfd.recv(1024).decode()
                 if data == "list":
                     tftp.do_list()
                 elif data == 'get':
                     tftp.do_get()
                 elif data == 'put':
                     tftp.do_put()
                 elif data == 'quit':
                     print("客户端退出")
                     sys.exit(0)
         else:
             connfd.close()
             continue

 if __name__ == "__main__":
     main()

tftp_server

 from socket import *
 import sys
 import time 

 class TftpClient(object):    #实现各种功能请求
     pass
 #创建套接字建立连接
 def main():
     if len(sys.argv) < 3:
         print("argv is error")
         return
     HOST = sys.argv[1]
     PORT = int(sys.argv[2])
     ADDR = (HOST,PORT)

     sockfd = socket()
     sockfd.connect(ADDR)

     tftp = TftpClient()   #__init__是否需要传参

     while True:
         print("打印界面")

         cmd = input("输入命令>>")

         if cmd == "list":
             tftp.do_list()

 if __name__ == "__main__":
     main()

tftp_client

tftp 文件服务器

项目功能 :

* 客户端有简单的页面命令提示
* 功能包含:
1. 查看服务器文件库中的文件列表(普通文件)
2. 可以下载其中的某个文件到本地
3. 可以上传客户端文件到服务器文件库

* 服务器需求 :1. 允许多个客户端同时操作
2.每个客户端可能回连续发送命令

技术分析:
1. tcp套接字更适合文件传输
2. 并发方案 ---》 fork 多进程并发
3. 对文件的读写操作
4. 获取文件列表 ----》 os.listdir()
粘包的处理

整体结构设计
1. 服务器功能封装在类中(上传,下载,查看列表)
2. 创建套接字,流程函数调用 main()
3. 客户端负责发起请求,接受回复,展示
服务端负责接受请求,逻辑处理

pythonNet08的更多相关文章

  1. python学习菜单

    一.python简介 二.python字符串 三.列表 四.集合.元组.字典 五.函数 六.python 模块 七.python 高阶函数 八.python 装饰器 九.python 迭代器与生成器  ...

随机推荐

  1. 图像等比例缩放的函数封装(PHP)

    <?php //图像等比例缩放函数 /** *等比例缩放函数(以保存新图片的方式实现) *@param string $picname 被缩放的处理图片源 *@param int $maxx 缩 ...

  2. python第三方库PIL安装的各种坑

    PIL python的图像处理库,pycharm安装屡次失败,始终报错 果断换依旧报错,查遍所有博客, 有给pip加参数的,pip install PIL --allow-external PIL - ...

  3. Github Clone to local files

    cd to you local files address key the word: git clone -0 github https://github.com/xxxxxxxxx Done... ...

  4. 快递100API接口开发

    api.kuaidi100.com 获得物流单号的跟踪信息(免费) 1.应用场景 2.是否需要授权 3.请求地址 4.输入参数 5.返回结果 6.返回示例 7.API工具 8.FAQ 通过向指定的地址 ...

  5. UVA-11613 Acme Corporation (最大费用最大流+拆点)

    题目大意:有一种商品X,其每每单位存放一个月的代价I固定.并且已知其每月的最大生产量.生产每单位的的代价.最大销售量和销售单价,还已知每个月生产的X能最多能存放的时间(以月为单位).问只考虑前m个月, ...

  6. Reverse engineer powerdesigner link odbc

    Reverse engineer powerdesigner link odbc           Option Explicit ValidationMode = True Interactive ...

  7. Cortex_M3——存储器系统学习笔记

    看完一个章节完全不做学习笔记总结并进行知识转换,看了就会忘记啊~无奈脸. 一.CORTEX_M3总线一览 二.异常 编号为1-15的对应系统异常,大于等于16的则全是外部中断. 系统异常清单如下所示: ...

  8. 058——VUE中vue-router之实例操作新闻列表单页面应用与路由别名的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. fcntl 改变描述符属性

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  10. Docker ENTRYPOINT

    entrypoint: 在启动镜像的时候会执行这个命令下的脚本,在docker run 和docker start情况下都会触发. 好比这个脚本是对某一个文件追加数据,每次start的时候都会追加,文 ...