zoukankan      html  css  js  c++  java
  • 学习笔记-Python基础16-多线程

    # 环境
    - windows7
    - anaconda
    - pycharm3.6
    # 多线程 vs 多进程
    - 程序:一堆代码以文本形式存入一个文档
    - 进程:程序运行的一个状态
    - 包含地址空间、内存、数据栈等
    - 每个进程有自己完全独立的运行环境,此时如果多进程想要共享数据就会遇到困难
    - 线程:一个进程的独立运行片段,一个进程可以有多个线程
    - 轻量化的进程
    - 一个进程的多个线程之间共享数据和上下文环境
    - 共享互斥问题
    - 全局解释器锁(GIL)
    - Python代码的执行是由python虚拟机进行控制
    - 在主循环中只能有一个控制线程在执行
    - Python包
    - thread:有问题,不好用,python3改成了_thread
        - 案例01.py:顺序执行。耗时较长
        - 案例02.py:改用多线程,缩短总用时,使用的是_thread
        - 案例03.py: _thread,传参数


     

       

       

      - threading:现在用的
      - 直接利用threading.Thread生成Thread实例
      1、t = threading.Thread(target=xxx, args=(xxx,))
      2、t.start() 启动多线程
      3、t.join() 等待多线程执行完成
      4、案例04.py

       

        - 守护线程 daemon
        - 如果在程序中将子线程设置成守护线程,则这个子线程会在主线程结束的时候自动退出
        - 一般认为,守护线程不重要或者不允许离开主线程独立运行
        - 守护线程案例能否有效果跟环境相关
        - 案例06.py 非守护线程
        - 案例07.py 守护线程

       

    
    
      - 线程常用属性:
      - threading.currentThread:返回当前线程变量
      - threading.enumerate:返回一个包含正在运行的线程的list,正在运行的线程指的是线程启动后,结束前
      - threading.activeCount:返回正在运行的线程数量,效果跟len(threading.enumerate)相同
      - thr.setName:给线程设置名字
      - thr.getName:得到线程名字
        线程常用属性案例08.py
        

                      

      - 直接继承自threading.Thread
      - 直接继承Thread
      - 重写run函数
      - 类实例可以直接运行
      - 案例09.py

    - 案例10.py 企业常用,工业风写法
     

          

      - 共享变量
      - 共享变量:当多个线程同时访问一个变量的时候,由于不是原子操作,导致会产生共享变量冲突
      - 案例11.py
         
        - 解决变量方案:锁、信号灯
    - 锁(Lock):
    - 是一个标志,表示一个线程在占用一些资源
    - 使用过程:
    - 上锁
    - 放心使用共享资源
    - 取消锁、释放锁
    - 案例12.py
    - 锁谁:哪个资源需要多个线程共享,就锁那个
    - 理解锁:锁其实不是锁住谁,而是一个令牌
    - 线程安全问题:
    - 如果一个资源/变量,它对于多线程来讲,不用加锁也不会引起任何问题,则称为线程安全
    - 线程不安全变量类型:list,set,dict
    - 线程安全变量类型:queue队列
     
    - 生产者消费者问题
    - 一个模型,可以用来搭建消息队列
    - queue是一个用来存放变量的数据结构,特点是先进先出,内部元素排队,可以理解成一个特殊的list
    import threading
    import time
    import queue
    # Python2
    # from Queue import Queue
    # Python3
    # import queue
    
    # 模拟生产者Producer类
    class Producer(threading.Thread):
        def run(self):
            global q
            count = 0
            while True:
                # queue.qsize()返回queue内容长度
                if q.qsize() < 1000:
                    for i in range(100):
                        count = count +1
                        msg = '生成产品'+str(count)
                        # put是往queue放入一个值
                        q.put(msg)
                        print(msg)
                time.sleep(0.5)
    # 模拟消费者Consumer
    class Consumer(threading.Thread):
        def run(self):
    
            global q
            while True:
                if q.qsize() > 100:
                    for i in range(3):
                        # q.get()是从queue中取出一个值
                        msg = self.name + "消费了" + q.get()
                        print(msg)
                time.sleep(1)
    if __name__ == "__main__":
        q = queue.Queue()
        for i in range(500):
            q.put('初始产品'+str(i))
        for i in range(2):
            p = Producer()
            p.start()
        for i in range(5):
            c = Consumer()
            c.start()
    
    
    
    # 死锁问题
    # 下面的例子讲的是:t1和t2两个线程同时跑func_1和func_2,func_1申请了lock_1之后睡了两秒,func_2申请了lock_2后睡了4秒,
    # func_1睡醒后要申请lock_2,func_2睡醒后要申请lock_1,但此时双方都未释放之前各自的申请锁,导致出现死锁 # 打印结果如下 ''' 主程序启动... func_1 starting... func_1 申请了 lock_1... func_2 starting... func_2 申请了 lock_2... func_1 等待2秒后执行 lock_2 申请... func_2 等待4秒后执行 lock_1 申请... ... import threading import time lock_1 = threading.Lock() lock_2 = threading.Lock() # 申请锁和释放锁的顺序相反 def func_1(): print("func_1 starting...") lock_1.acquire() print("func_1 申请了 lock_1...") time.sleep(2) print("func_1 等待2秒后执行 lock_2 申请...") lock_2.acquire() print("func_1 申请了 lock_2...") lock_2.release() print("func_1 释放了 lock_2") lock_1.release() print("func_1 释放了 lock_1") print("func_1 done...") def func_2(): print("func_2 starting...") lock_2.acquire() print("func_2 申请了 lock_2...") time.sleep(4) print("func_2 等待4秒后执行 lock_1 申请") lock_1.acquire() print("func_2 申请了 lock_1...") lock_1.release() print("func_2 释放了 lock_1...") lock_2.release() print("func_2 释放了 lock_2...") print("func_2 done...") if __name__ == "__main__": print("主程序启动...") t1 = threading.Thread(target=func_1, args=()) t2 = threading.Thread(target=func_2, args=()) t1.start() t2.start() t1.join() t2.join() print("主程序结束...")

      

    # 死锁问题解决方法1:根据申请锁的等待时间timeout延长申请时间,之后获取其返回值判断成功与否
    '''
    主程序启动...
    func_1 starting...
    func_1 申请了 lock_1...
    func_2 starting...
    func_2 申请了 lock_2...
    func_1 等待2秒后执行 lock_2 申请...
    func_2 等待4秒后执行 lock_1 申请...
    func_1 等了两秒也没申请到 lock_2...
    func_1 释放了 lock_1
    func_1 done...
    func_2 申请了 lock_1...
    func_2 释放了 lock_1...
    func_2 释放了 lock_2...
    func_2 done...
    主程序结束...
    '''
    import threading
    import time
    
    lock_1 = threading.Lock()
    lock_2 = threading.Lock()
    
    # 申请锁和释放锁的顺序相反
    # 假定func_1肯定能申请到lock_1
    # 假定func_2肯定能申请到lock_2
    def func_1():
        print("func_1 starting...")
        lock_1.acquire(timeout=4)
        print("func_1 申请了 lock_1...")
        time.sleep(2)
        print("func_1 等待2秒后执行 lock_2 申请...")
        # 申请锁2返回值,成功True
        rst = lock_2.acquire(timeout=2)
        if rst:
            print("func_1 已经得到锁 lock_2...")
            lock_2.release()
            print("func_1 释放了 lock_2...")
        else:
            print("func_1 等了两秒也没申请到 lock_2...")
        lock_1.release()
        print("func_1 释放了 lock_1")
    
        print("func_1 done...")
    
    def func_2():
        print("func_2 starting...")
        lock_2.acquire()
        print("func_2 申请了 lock_2...")
        time.sleep(4)
        print("func_2 等待4秒后执行 lock_1 申请...")
    
        lock_1.acquire()
        print("func_2 申请了 lock_1...")
        lock_1.release()
        print("func_2 释放了 lock_1...")
        lock_2.release()
        print("func_2 释放了 lock_2...")
    
        print("func_2 done...")
    if __name__ == "__main__":
        print("主程序启动...")
        t1 = threading.Thread(target=func_1, args=())
        t2 = threading.Thread(target=func_2, args=())
        t1.start()
        t2.start()
    
        t1.join()
        t2.join()
        print("主程序结束...")
    # 死锁问题的解决方法2:semaphore 
    - 允许一个资源最多可以几个线程同时使用,信号灯的意思
    - 案例16.py

    - threading.Timer 定时器
    - Timer是利用多线程,在指定时间后启动一个功能
    - 案例17.py

    - 可重入锁 
    - 一个锁,可以被一个线程多次申请
    - 主要解决递归调用的时候,需要申请锁的情况
    - 案例18.py

        
  • 相关阅读:
    shell 格式化输出
    Linux tar 修改终端命令
    uniqu 用法
    HashMap按照value值进行排序
    汇编语言系列教程之基础入门 (一)
    Linux权限管理
    linux用户管理
    vim的tab键设定
    HTTP请求(GET与POST区别)和响应
    JS eval()
  • 原文地址:https://www.cnblogs.com/Cloudloong/p/9773784.html
Copyright © 2011-2022 走看看