学习笔记☞python3☞网络编程(八) ☞【线程同步互斥方法(二)、GIL问题(全局解释器锁)、设计模式、服务器模型、HTTP文件服务器】

线程同步互斥方法(二)

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值