线程通信

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

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

线程的同步互斥

线程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. Solidity 官方文档中文版 4_Solidity 编程实例

    Voting 投票 接下来的合约非常复杂,但展示了很多Solidity的特性.它实现了一个投票合约.当然,电子选举的主要问题是如何赋予投票权给准确的人,并防止操纵.我们不能解决所有的问题,但至少我们会 ...

  2. 使用 Git Hook 自动部署 Hexo 到个人 VPS

    安装 Hexo 既然我的标题都已经那样写了,当然这个小节就不是本篇文章的重点了. 关于 Hexo 的安装跟配置,其实网上已经有很多很多文章了,随便一搜一大把.这里就有一篇超详细的,大家可以参考一下. ...

  3. hihocoder1513

    https://hihocoder.com/problemset/problem/1513 五维偏序问题,直接bitset压位,复杂度O(n^2/32) (本来想写三维偏序,但是cdq不会只好写写五维 ...

  4. Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制

    Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...

  5. VGG16提取图像特征 (torch7)

    VGG16提取图像特征 (torch7) VGG16 loadcaffe torch7 下载pretrained model,保存到当前目录下 th> caffemodel_url = 'htt ...

  6. UVA-1152 4 Values whose Sum is 0 (二分)

    题目大意:在4个都有n个元素的集合中,每个集合选出一个元素,使得4个数和为0.问有几种方案. 题目分析:二分.任选两组求和,剩下两组求和,枚举第一组中每一个和sum,在第二组和中查找-sum的个数,累 ...

  7. Oracle Sourcing Implementation and Administration Guide(转)

    原文地址 Oracle Sourcing Implementation and Administration Guide

  8. 本地Run Page时报检测到意外的 URL 参数,它将被忽略。

    经查,是因为我RUN的时候 Target URL -- http://MY-PC:8988/OA_HTML/runregion.jsp 将MY-PC更改为本地IP即可. 设置方法 Tools - Em ...

  9. https ddos攻击——由于有了认证和加解密 后果更严重 看绿盟的产品目前对于https的ddos cc攻击需要基于内容做检测

    如果web服务器支持HTTPS,那么进行HTTPS洪水攻击是更为有效的一种攻击方式,一方面,在进行HTTPS通信时,web服务器需要消耗更多的资源用来进行认证和加解密,另一方面,一部分的防护设备无法对 ...

  10. 【hive】时间段为五分钟的统计

    问题内容 今天遇到了一个需求,需求就是时间段为5分钟的统计.有数据的时间戳.对成交单量进行统计. 想法思路 因为数据有时间戳,可以通过from_unixtime()来获取具体的时间. 有了具体的时间, ...