zoukankan      html  css  js  c++  java
  • day 34

    1 .内容回顾

    #__author : 'liuyang' 
    #date : 2019/4/17 0017 上午 9:01
    # 利大于弊,则做之
    # 会死于斯,则不去
    #  2个 人  晚上  5个题  面试题
    #  今晚 7点 考试题
    #  五一之前  要考试
        #其它内容(40%) 网编并发数据库(60%)
    
    #
        #互斥锁
        #能够保护数据的安全性
            #保证对于数据的修改操作同一时刻多个进程只有一个进程执行
        #进程数据不安全:同时修改文件/数据库/其它共享资源的数据
    
    # 队列---实现了进程之间的通信(IPC)
    
        #进程队列  ----进程安全
            #从mutltiprocessing  导入Queue
            #q = Queue()
            #put/get
        # 基于管道+管道 ,管道 进程不安全
        # 管道 基于文件级别的socket 实现的
    
    import queue
    from multiprocessing import Queue
    # 生产者消费模型
    #  put  get  两个阻塞方法
    # put_nowait(丢数据)/ get_nowait 非阻塞方法
    q = Queue(5)        #队列里有五个
    q.put(1)
    q.put(1)
    q.put(1)
    q.put(1)
    q.put(1)
    print('_____________')
    try :
            q.put_nowait(1)     #也传一个
    except queue.Full:
        # 存在这里
        pass
    # q.put(1)
    print('______')
    # q.put(1)
    print('__')
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    # print(q.get())
    
    # print(q.get())
    # print(q.get())
    # print(q.get())
    
    try :
        print(q.get_nowait())
    except queue.Empty:
        pass
    
    # 网页版的  qq
    # sereve  端   djiong  写的
    # 信息一直没有 一直夯在这  于是 用get_nowait()  没数据立刻返回
    # 隔个0.5秒  再返回来查看
    
    # 生产者 消费者 模型
        # 达到效率平衡
        # 一个生产数据和消费数据的完整的流程解耦解耦成两个部分:生产和消费
        #由于生产速度和消费速度不一致,所以需要我们调整生产者和消费者额d个数来达到效率平衡
    View Code

    2.今日内容

    #1 互斥锁
    #2 进程之间的数据共享
        #关于数据安全的问题
    #3 进程池
        #from multiprocessing import Pool
    # 事件信号量管道
    # 4 线程的概念(面试的重点)
    # 5 认识线程模块

    3.什么是互斥锁 

    # 在多个进程中 或者一个进程中 

    # 有acquire()acquire()就阻在那里了

    #__author : 'liuyang' 
    #date : 2019/4/17 0017 上午 9:27
    # from multiprocessing import Lock
    # #1  互斥锁:不能在同一个进程内,‘也’有锁的竞争关系
    # # 在同一个进程中连续acquire多次会产生死锁
    # lock = Lock()
    # lock.acquire() #拿走钥匙
    # print(1)
    # lock.acquire() #被拿走了又想要钥匙 卡住 #互斥
    # print(2)
    # # lock.release() #没还钥匙  卡在第一个开锁那
    # lock.release()
    # lock.release()
    View Code

    4.数据共享(进程内可以但是不大需要)

    # 本来是数据隔离的

    # 加上Manager就可以分享了

    #__author : 'liuyang' 
    #date : 2019/4/17 0017 上午 9:35
            #数据共享几乎不用
    # 数据共享: 可以, Manager  但是不安全
    # 可以 安全  加锁
    
    from multiprocessing import Process,Manager,Lock
    def func(dic):
        dic['count'] -= 1
    
            # 数据不共享 正常情况下数据隔离 子进程改
    if __name__ == '__main__':
        lock = Lock()
        m = Manager()
        dic = m.dict({'count':100})
        p_l = []
        for i in range(100):
            p = Process(target=func,args=(dic,lock))
            p.start()
            p_l.append(p)
        for p in p_l : p.join()
        print(dic)  #{'count': 0} 性能越好 越不得零
    
    # 100 减 100次 1 这么慢? 不是减操作造成的
    # 慢是因为 开100个进程  所以慢  开和管理 销毁进程拖慢了程序的运行效率
    
    # 为什么在这里出现了数据不安全的现象?
        # 正常不会数据共享  隔离 肯定通过socket 文本或者网络传过来的
        # (不丢失)性能快的时候,比如两个 子进程同时对一样的值操作了,返回的一样的值
    
    #什么情况会出现数据不安全:Manager 类当中对字典/列表  += -= *= /=
                            #添加值 不会
    #如何解决 : 加锁
    
    #  修改的 异步 性能高了会出错对同一个进行操作  #加锁同步安全
    #  查看的 异步快
    
    # cpu个数  最多起cpu*2个
        #
    View Code

    5.多线程

    cpython解释器内置的 GIL锁,同步

    为了数据安全 

    解释性语言(一边解释一边编译 解释的字节码 无序 所以操作造成异步操作 数据不安全)

    编译型语言可以实现多进程

    #__author : 'liuyang' 
    #date : 2019/4/17 0017 上午 10:18
    # 线程是进程中的一个单位
    # 进程是计算机中最小的资源分配单位
    # 线程是计算机中被CPU调度的最小单位
    
    # 开启进程 关闭进程 切换进程都需要时间
    # 你的电脑的资源还是优先的
    # 开启过多的进程会导致你的计算机崩溃
    
    # count_cpu*2 = 8  #4 核
    # 同时对8个客户端服务
    # qps 每秒的请求数  2W
    
    # 2000/8 = 250 台机器
    
    # 进程: 数据隔离的
        #ftp server端
        #qq  server端(不用隔离,本来就不传输,得写了才传)
    # 并发: 同一时刻能同时接受多个客户端的请求
    # 进程有大 有数据隔离  开多了还不行  (有的不需要隔离,还要ipc传输过来、)
    
    #线程:
        # 轻型进程 轻量级的进程
        # 在同一个进程中的多个线程是可以共享一部分数据的
        # 线程的开启销毁切换都比进程要高级很多
    
    #1.多个进程可不可以利用多核(多个CPU)
    #2.多个线程可不可以利用多核(多个CPU)
    #  都可以
    
    # 多进程和多线程之间的区别
        #进程 数据隔离  开销大 (必须数据隔离是才会进程)
        #线程 数据共享  开销小
    
    # python 当中的多线程
        # Cpython 解释器  有一个GIL锁  (怕麻烦 要不太多修改的)
        #
    
    # (解释性语言)  编译 --》字节码(bytes) 没法正常排序的-->机器码(0101)
    # python 代码机器语言
    from dis import dis
    def func():
        a = []
        a.append(1)
    dis(func)
    '''
     42           0 BUILD_LIST               0
                  2 STORE_FAST               0 (a)
    
     43           4 LOAD_FAST                0 (a)
                  6 LOAD_ATTR                0 (append)
                  8 LOAD_CONST               1 (1)      #加载他们几个存在内存里
                 10 CALL_FUNCTION            1          #调用
                 12 POP_TOP                     
                 14 LOAD_CONST               0 (None)
                 16 RETURN_VALUE''' #默认返回空
    # 两个程序在两个cpu上同时触发,就可能造成数据不安全
    # python 解释器(自动加锁) 同一时刻 只能有一个线程执行(单线程)
    
    # 解释性语言(python,php)  都不能多个程序(线程)访问多个cpu     #(异步执行无序)所以数据不安全
    # 编译型语言(c,java)  都能多个程序(线程)访问多个cpu
    
    # GIL 锁 历史遗留问题(python诞生时没有多核)
        #线程中的状态 就不如编译型语言 那么完美
    
    
    
    
    # python 当中的多线程(不是python的锅,可以解决的,没必要)
        # 不能访问多个cpu
        # 是Cpython(解决不了高运算) 解释器导致的      #不同的工具不同的功能
                                                #每个工具都不是万能的
        # GIL = 全局解释器锁 导致了同一时刻只能有一个线程访问cpu
        # pypy  没有GIL锁  Jpython  解释成java 可以多线程访问多核的 (但是他们的执行效率慢)
    
    
    
    
    # 研究pypy(和cpython速度相近了) 不如直接研究 go
        # go 的执行效率 和 c相近了
    
    #利用 多核意味着 多个CPU可以同时计算线程中的代码
    
    # IO 操作
        #accept负责从网络上读取数据
        #open() 调用操作系统的指令   0.9ms的时间 (cpu执行450万条指令(在阻塞))
        #read               #7个指令 一行代码 50w/7 7w条 python 代码  千分之一秒 执行的
    
    
    # 分布式多进程
        #大量的计算 可以开 多进程 进多核  高额业务
    
                # ftp 这样的大部分都是网络和进程都无关
    # web 框架    #大部分时间 都是金阻塞  io呢 文件呢 网络呢  没大进cpu进行
                    #所以单进程多线程就够了
        #Django flask  tornado  twistwed  scrapy  sanic
        #都 并发 多线程  没有用进程
    
    #  解释性和 编译型  的  因为一边翻译 一边编译   不如 直接汉语好   英语放过来

      

     6.python代码实现  thread(进程)

    #__author : 'liuyang' 
    #date : 2019/4/17 0017 上午 11:34
    # 利 = 1
    # 弊 = 2
    # do = 'do'
    # if 利 > 弊:
    #     do
    #
    import threading
    # threading 和 multtiprocessing
    # 先有的threading模块
        #没有池的功能
    #multiprocessing 完全模仿threading 模块完成的
        #实现了池的功能
    #concurrent.futures
        #实现了线程池进程池
    
    # import os
    # import time
    # from threading import Thread
    # def func(i):     #子线程
    #     time.sleep(1)   #阻塞了之后 cpu就绪 执行就不在控制范围内  了所以不按顺序
    #     print('in func',i, os.getpid())
    #
    # print('in main',os.getpid())
    #             #一个线程的时间开启和管理的时间不是固定的 开的时候有可能cpu很闲
    #                     #直接执行了
    #
    # for i in range(20):     #并发     #异步不是一起执行
    #     Thread(target=func,args=(i,)).start()
        #func()  #同步20 秒  20倍差别
    #in main 4676
    # in func 4676
    # 在一个进程里
    
    # if __name__ =='__main__':   #多个线程都是 共享的  没有import没有导入
                                    # 不会被执行 所以 不用
            # 在线程部分不需要通过import来为新的线程获取代码
            # 因为新的线程和之前的主线程共享同一段代码
            # 不需要import 也就不存在  子进程中有重复了一次
    
    # 开销    # 进程和线程的代码管理 是一样的 因为都是开和关 没必要有差距
    # 数据隔离
    #
    # from multiprocessing import Process
    # from threading import Thread
    # import time
    # def func(a):
    #     a += 1
    # if __name__ =='__main__':
    #     start = time.time()
    #     t_l = []
    #
    #     for i in range(100):
    #         t = Thread(target=func,args=(i,))
    #         t.start()
    #         t_l.append(t)
    #     for t in t_l : t.join() # 确保前面都执行完
    #     print('thread',time.time() - start )
    #
    #     start = time.time()
    #     t_l = []
    #
    #     for i in range(100):
    #         t = Process(target=func, args=(i,))
    #         t.start()
    #         t_l.append(t)
    #     for t in t_l: t.join()  # 确保前面都执行完
    #     print('process',time.time() - start)
    #
    #     #t 0.0870048999786377
    #     # p 7.8074469566345215
        # 100倍   开进程倍
    
    # 多个线程之间的全局变量是共享的
    #
    # from multiprocessing import Process
    # from threading import Thread
    # import time
    # tn = 0
    # def func(a):
    #     global tn
    #     tn  += 1
    # if __name__ =='__main__':
    #     start = time.time()
    #     t_l = []
    #
    #     for i in range(100):
    #         t = Thread(target=func,args=(i,))
    #         t.start()
    #         t_l.append(t)
    #     for t in t_l : t.join() # 确保前面都执行完
    #     print('thread',time.time() - start )
    #     print(tn)
    #
    # # 进程之间数据隔离
    # pn = 0      # 这里定义了 所以不报错
    # def func(a):
    #     global pn
    #     pn  += 1
    #
    # if __name__ == '__main__':
    #
    #     start = time.time()
    #     t_l = []
    #
    #     for i in range(100):
    #         t = Process(target=func, args=(i,))
    #         t.start()
    #         t_l.append(t)
    #     for t in t_l: t.join()  # 确保前面都执行完
    #     print('process',time.time() - start)
    #     print(pn)
    
     # 线程中的几个替他方法
    from threading import Thread,currentThread  #线程对象
    import os
    def func():
        t = currentThread()     #线程属于哪个id的
        print(t.name,t.ident,os.getpid())
        # print(currentThread(),os.getpid())
    
    tobj = Thread(target=func)
    tobj.start()
    print('tobj:',tobj)
    # print(currentThread(),os.getpid())
    '''
    Thread-1 9224 9612
    <_MainThread(MainThread, started 4108)> 9612
    <Thread(Thread-1, started 9224)> 9612
    '''
    '''
    Thread-1 8800 9588          #巧了 异步一样
    tobj: <Thread(Thread-1, stopped 8800)>'''
    
    lst = [1,2,3,4,5,6,7,8,9,10]
    #按照顺序把列表中的每一个元素都计算一个平方
    #使用多线程方式
    # #并且将结果按照顺序返回
    from threading import Thread   #线程对象
    import time
    import random
    dic = {}
    def func(i):
        t = currentThread()
        time.sleep(random.random())
        dic[t.ident] = i**2
    t_l = []
    for i in range(1,11):
        t = Thread(target=func, args=(i,))
        t.start()
        t_l.append(t)
    for t in t_l:
        t.join()  # 确保前面都执行完
        print(dic[t.ident])
    print(dic)  #{7936: 81, 6056: 4, 9344: 49, 10188: 9, 6648: 100, 7264: 64, 4072: 16, 9924: 36, 8796: 1, 7216: 25}
                    #这不是 按顺序添加的 只是显示是顺序的  添加是按顺序的
    
    # from threading import active_count
    # # 返回当前正在工作的线程
    # from threading import Thread   #线程对象
    # import time
    # import random
    # l = []
    # def func(a):
    #     t = currentThread()
    #     time.sleep(random.random())
    # for i in range(1,11):
    #     t = Thread(target=func, args=(i,))
    #     #t.start()  11 个     不start() 就不执行
    # print(active_count())     #1   #只有一个主线程
    
    # 线程有terminate 么?
        #没有terminate 不能强制结束
        #所有的子线程都会在执行完所有的任务之后结束
    
    # 统计线程的id  统计正在执行的线程数   用法差不多 没有terminate
    
    # 1 . 通读博客  :操作系统 ,进程,线程
    # 2 . 把课上的代码都搞明白
    # 3.  多线程实现一个并发  tcp协议的socket_server
    # 4.  明天默写和线程相关的
    View Code
  • 相关阅读:
    让你彻底明白什么叫游戏引擎(1)
    今后几年将有多于28部游戏电影面世
    Symbian系统体系结构
    让你彻底明白什么叫游戏引擎(2)
    网易程序笔试题
    [转贴]暴雪的霸王条款是否合理?
    CPU GPU设计工作原理《转》
    求伯君:向暴雪学习 金山不求一夜暴富
    我的职业规划
    网络游戏程序员新手入门 [转]
  • 原文地址:https://www.cnblogs.com/Doner/p/10722369.html
Copyright © 2011-2022 走看看