• 多进程(补充),多线程,锁


    多进程补充
    joinable Queue

    q=JoinableQueue
    q.put(1)
    q.put(2)
    print(q.get())
    q.task_done() 告诉容器已经处理完成了一个数据 有几个数据就要调用几次
    q.task_done()

    q.join() 也是一个阻塞函数 一直到队列中的数据被处理完毕(task_done的调用次数等于队列中的数据数量)
    print('处理完成')

    # from multiprocessing import  Process,Queue,JoinableQueue
    # import time,random
    #
    # # 生产者
    # def make_hot_dog(q):
    #     for i in range(1,6):
    #         time.sleep(random.randint(1,3))
    #         print("33[46m生产者 生产了hot_dog%s33[0m" % i)
    #         q.put("hot_dog%s" % i)
    # # 消费者
    # def eat_hot_dog(q):
    #     while True:
    #         time.sleep(random.randint(1, 2))
    #         hot_dog = q.get()
    #         print("思聪吃了%s" % hot_dog)
    #         q.task_done()
    #
    #
    # if __name__ == '__main__':
    #     # 共享数据的队列
    #     q = JoinableQueue()
    #
    #     # 生产者
    #     p1 = Process(target=make_hot_dog,args=(q,))
    #     p2 = Process(target=make_hot_dog,args=(q,))
    #     p1.start()
    #     p2.start()
    #
    #
    #     # 消费者
    #     c1 = Process(target=eat_hot_dog,args=(q,))
    #     c1.daemon = True
    #     c1.start()
    #
    #     # print("完成了吗???")
    #     #先要确定生产者已经不会再生产了
    #     p1.join()
    #     p2.join()
    #
    #     print("生产已经结束了...")
    #     #再确定队列中的所有数据都被处理完成
    #     q.join()
    #     print("思聪已经全部吃完了....")
    #
    #
    #     # c1.terminate()
    #     #王思聪就不需要在吃了
    生产者消费者模型



    进程池
    1.多线程理论(重点)
    2.多线程使用方法(重点)
    两种创建方式
    常用属性

    互斥锁
    死锁


    操作系统就像一个工厂

    线程值的是一条流水线 整个执行过程的总称 也是一个抽象概念
    线程是CPU的最小执行单位 是具体负责执行代码的

    进程是一个资源单位,其中包括了改程序运行所需的所有资源
    线程相当于车间里的一条流水线
    线程的特点:
    一个进程中至少包括一个线程 是由操作系统自动创建的 称之为主线程
    一个进程中可以有任意数量的线程
    创建线程的开销对比进程而言 要小的多
    同一个进程中的线程间数据是共享的(最主要的特点)

    如何使用:使用的方式与进程一致
    不同的是:创建线程的代码可以写在任何位置

    from threading import Thread
    # 第一种 开启线程的方式 直接实例化Thread类
    # from threading import Thread
    #
    # def task():
    #     print('running....')
    #
    #
    # if __name__ == '__main__':
    #     t=Thread(target=task)
    #     t.start()
    #     print('over')
    #
    # # 2.继承Thread类  覆盖run方法
    # class MyThread(Thread):
    #     def run(self):
    #         print('running...')
    # MyThread().start()
    # #t=MyThread()
    # #t.start()
    两种线程创建方式



    开启线程速度 比开启进程快很多

    主线程任务执行完毕后 进程不会立即结束 会等待所有子线程执行完毕
    在同一进程中 所有线程都是平等的 没有子父一说
    from threading import Thread
    import time

    def task():
    print("子线程 running.....")
    time.sleep(3)
    print("子线程 over......")

    t = Thread(target=task)
    t.start()
    print("main over")

    线程与进程的区别之一 数据是共享的
    区别二 创建进程与创建线程的开销 大约是一百多倍

    from multiprocessing import  Process
    import os
    def task():
        print(os.getpid())
        pass
    
    if __name__ == '__main__':
    
        start = time.time()
        ps = []
        for i in range(100):
            p = Thread(target=task)
            # p = Process(target=task)
            p.start()
            ps.append(p)
    
        for p in ps:
            p.join()
    
        print(time.time()-start)


    线程安全也是通过锁来保证 所得用法与进程中一模一样
    # import time
    # from threading import  Thread,Lock
    #
    # num = 10
    # lock = Lock()
    #
    # def task():
    #     global num
    #     # lock.acquire()
    #     a = num
    #     time.sleep(0.1)
    #     num = a - 1
    #     # lock.release()
    #
    #
    # ts = []
    # for i in range(10):
    #     t = Thread(target=task)
    #     t.start()
    #     ts.append(t)
    #
    # for t in ts:
    #     t.join()
    #
    #
    # print(num)
    线程安全
    
    
    


    开发高并发程序很有可能遇到安全问题
    解决方案只有加锁 但是在使用锁时 很有可能出现死锁问题

    出现死锁问题的两种情况:
    1.对同一把锁调用了多次acquire 导致死锁问题(最low的死锁问题 应该避免这种问题)
    2.有多把锁,一个线程抢一把锁,要完成任务必须同时抢到所有的锁 将导致死锁问题
    from threading import Lock,Thread
    import time
    
    # lock = Lock()
    # lock.acquire()
    # lock.acquire()
    # print("over")
    
    # 一个盘子 和一双筷子
    # lock1 = Lock()
    # lock2 = Lock()
    #
    # def task1(name):
    #     lock1.acquire()
    #     print("%s 抢到了盘子" % name)
    #
    #     time.sleep(1)
    #
    #     lock2.acquire()
    #     print("%s 抢到了筷子" % name)
    #
    #     print("%s 吃饭了....." % name)
    #
    #     lock1.release()
    #     lock2.release()
    #
    #
    # def task2(name):
    #     lock2.acquire()
    #     print("%s 抢到了筷子" % name)
    #
    #     lock1.acquire()
    #     print("%s 抢到了盘子" % name)
    #
    #     print("%s 吃饭了....." % name)
    #
    #     lock1.release()
    #     lock2.release()
    #
    #
    #
    # t1 = Thread(target=task1,args=("渣渣辉",))
    # t1.start()
    #
    # t2 = Thread(target=task2,args=("大导演",))
    # t2.start()
    死锁

    如何避免:
    1.能不加锁就不加
    2.如果一定要加 要保证锁只有一把

    RLock只能防止同一个问题 统一线程多次执行acquire

    from threading import RLock
    
    # lock = RLock()
    # lock.acquire()
    # lock.acquire()
    # lock.acquire()
    # lock.acquire()
    #
    # print("over")
    # lock = RLock()
    #
    # def task1():
    #     lock.acquire()
    # def task2():
    #     lock.acquire()
    #
    # Thread(target=task1).start()
    # Thread(target=task2).start()



    信号量 Semaphore(num) 可以控制同一时间有多少线程可以并发的访问
    不是用来处理线程安全问题

    from threading import Semaphore
    
    s_lock = Semaphore(3)
    
    def task():
        s_lock.acquire()
        time.sleep(1)
        print("run.....")
        s_lock.release()
    
    for i in range(20):
        t = Thread(target=task)
        t.start()


    threading.current_thread() # 获取当前线程
    threading.active_count() 正在运行中的线程数量
    threading.enumerate() 返回所有正在运行的线程对象


    守护线程会在主线程结束后立即结束 即使任务没有完成
    主线程会等待所有子线程全部完成后才会结束


    守护线程会在所有非守护线程结束后 结束*****

    主线 守护线程
    主线程要等待所有子线程结束

    from threading import Semaphore
    
    s_lock = Semaphore(3)
    
    def task():
        s_lock.acquire()
        time.sleep(1)
        print("run.....")
        s_lock.release()
    
    for i in range(20):
        t = Thread(target=task)
        t.start()
  • 相关阅读:
    BZOJ2337 [HNOI2011]XOR和路径
    「学习笔记」3.31代码学习
    uva live 12846 A Daisy Puzzle Game
    Cannot use ImageField because Pillow is not installed
    Android点击Button水波纹效果
    hdu 1241 Oil Deposits
    c++ 字符输入读取
    clutter recoder
    C/C++获取数组长度
    vector array and normal stanard array
  • 原文地址:https://www.cnblogs.com/gengbinjia/p/10489955.html
Copyright © 2020-2023  润新知