线程通信

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

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

线程的同步互斥

线程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. Educational Codeforces Round 17 C. Two strings 打表二分

    C. Two strings time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  2. Android反射机制:手把手教你实现反射

    什么是反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称 ...

  3. 【Docker】Windows下docker环境搭建及解决使用非官方终端时的连接问题

    背景 时常有容器方面的需求,经常构建调试导致测试环境有些混乱,所以想在本地构建一套环境,镜像调试稳定后再放到测试环境中. Windows Docker 安装 安装docker toolbox 博主的电 ...

  4. 利用Minhash和LSH寻找相似的集合(转)

    问题背景 给出N个集合,找到相似的集合对,如何实现呢?直观的方法是比较任意两个集合.那么可以十分精确的找到每一对相似的集合,但是时间复杂度是O(n2).当N比较小时,比如K级,此算法可以在接受的时间范 ...

  5. 人工神经网络 Artificial Neural Network

    2017-12-18 23:42:33 一.什么是深度学习 深度学习(deep neural network)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高 ...

  6. python2和python3的区别——持续更新

    1.在 cookbook 上看到的,python3支持 *运算符 来接收迭代变量,如: a, *b = [, , , ] python2是不支持的! 2.在 cookbook 上看到的,python3 ...

  7. Android------个人项目(歆语气象通)

    歆语气象通: 歆语气象伴随你的身边,便捷生活. 包含了以下功能: 1. 天气预报数据覆盖中国城市和地区:2. 提供一周天气预报及最低最高温度,时刻关注天气,轻松计划出行:3. 各种指数详细信息,如太阳 ...

  8. Android之水波纹点击效果(RippleView)

    Android5.0后各种炫的效果纷纷出来,写这篇博客主要是讲的是按钮点击效果带有的水波纹(波浪式). 当然我写的这个是自定义来实现的,在低版本(5.0一下)也可以实现点击效果.看看效果图: 上图可看 ...

  9. 增加 修改oracle约束条件

    ALTER TABLE    TB_ZJGL_DWSB_GRMX ADD CONSTRAINT SFZH_UNIQUE UNIQUE(SFZH);    ALTER TABLE TB_ZJGL_DWS ...

  10. linux下redis的安装及配置启动

    linux下redis的安装及配置启动 标签: redisnosql 2014-10-24 14:04 19732人阅读 评论(0) 收藏 举报  分类: 数据与性能(41)  wget http:/ ...