• day 32 操作系统、线程和进程(GIL锁)


    一、操作系统/应用程序

    a. 硬件 
        - 硬盘
        - CPU 
        - 主板 
        - 显卡
        - 内存
        - 电源
        ...
    b. 装系统(软件)
        - 系统就是一个由程序员写出来软件,该软件用于控制计算机的硬件,让他们之间进行相互配合。
        
    c. 安软件(安装应用程序)
        - QQ
        - 百度云
        - pycharm

    二、并发和并行

    并发,伪,由于执行速度特别快,人感觉不到停顿。
    并行,真,创建10个人同时操作。

    三、线程和进程

    a. 单进程、单线程的应用程序
    print('666')
    最简单
    b. 到底什么是线程?什么是进程?
      Python自己没有这玩意,Python中调用的操作系统的线程和进程。
    
    c. 单进程、多线程的应用程序
      一个应用程序(软件),可以有多个进程(默认只有一个),一个进程中可以创建多个线程(默认一个)
    import threading
    print('666')
    
    def func(arg):
        print(arg)
    t = threading.Thread(target=func)
    t.start()
    
    print('end')
    代码
    d. 故事: Alex甄嬛西游传

      总结:

        1. 操作系统帮助开发者操作硬件。
        2. 程序员写好代码在操作系统上运行(依赖解释器)。

    import threading
    import requests
    import uuid
    
    url_list = [
        'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
        'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
        'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
    ]
    
    def task(url):
        ret = requests.get(url)
        file_name = str(uuid.uuid4()) + '.jpg'
        with open(file_name, mode='wb') as f:
            f.write(ret.content)
    
    for url in url_list:
        task()
    
    
    """
    - 你写好代码
    - 交给解释器运行: python s1.py 
    - 解释器读取代码,再交给操作系统去执行,根据你的代码去选择创建多少个线程/进程去执行(单进程/单线程)。
    - 操作系统调用硬件:硬盘、cpu、网卡....
    """
    以前的你,写代码:
    import threading
    import requests
    import uuid
    
    url_list = [
        'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
        'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
        'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
    ]
    
    def task(url):
    
        ret = requests.get(url)
        file_name = str(uuid.uuid4()) + '.jpg'
        with open(file_name, mode='wb') as f:
            f.write(ret.content)
    
    for url in url_list:
    
        t = threading.Thread(target=task,args=(url,))
        t.start()
    
    
    """
    - 你写好代码
    - 交给解释器运行: python s2.py 
    - 解释器读取代码,再交给操作系统去执行,根据你的代码去选择创建多少个线程/进程去执行(单进程/4线程)。
    - 操作系统调用硬件:硬盘、cpu、网卡....
    """
    现在的你,写代码:
        Python多线程情况下:
            - 计算密集型操作:效率低。(GIL锁)
            - IO操作: 效率高 
            
        Python多进程的情况下:
            - 计算密集型操作:效率高(浪费资源)。 不得已而为之。
            - IO操作: 效率高 (浪费资源)。
        
        以后写Python时:
            IO密集型用多线程: 文件/输入输出/socket网络通信
            计算密集型用多进程。
        
        
        扩展:
            Java多线程情况下:
                - 计算密集型操作:效率高。
                - IO操作: 效率高 
            Python多进程的情况下:
                - 计算密集型操作:效率高(浪费资源)。
                - IO操作: 效率高 浪费资源)。

    四、Python中线程和进程(GIL锁)

    GIL锁,全局解释器锁。用于限制一个进程中同一时刻只有一个线程被cpu调度。
    
    扩展:默认GIL锁在执行100个cpu指令(过期时间)。

    五、python线程编写

    # by luffycity.com
    import threading
    
    # #################### 1. 计算密集型多线程无用 ####################
    # v1 = [11,22,33] # +1
    # v2 = [44,55,66] # 100
    #
    #
    # def func(data,plus):
    #     for i in range(len(data)):
    #         data[i] = data[i] + plus
    #
    # t1 = threading.Thread(target=func,args=(v1,1))
    # t1.start()
    #
    # t2 = threading.Thread(target=func,args=(v2,100))
    # t2.start()
    
    
    # #################### 2. IO操作 多线程有用 ####################
    # import threading
    # import requests
    # import uuid
    #
    # url_list = [
    #     'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
    #     'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
    #     'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
    # ]
    #
    # def task(url):
    #     ret = requests.get(url)
    #     file_name = str(uuid.uuid4()) + '.jpg'
    #     with open(file_name, mode='wb') as f:
    #         f.write(ret.content)
    #
    # for url in url_list:
    #
    #     t = threading.Thread(target=task,args=(url,))
    #     t.start()
    View Code
    # by luffycity.com
    import threading
    
    
    # ###################### 1.线程的基本使用 #################
    # def func(arg):
    #     print(arg)
    #
    #
    # t = threading.Thread(target=func,args=(11,))
    # t.start()
    #
    #
    # print(123)
    # ###################### 2.主线程默认等子线程执行完毕 #################
    # import time
    # def func(arg):
    #     time.sleep(arg)
    #     print(arg)
    #
    #
    # t1 = threading.Thread(target=func,args=(3,))
    # t1.start()
    #
    # t2 = threading.Thread(target=func,args=(9,))
    # t2.start()
    #
    # print(123)
    # ###################### 3.主线程不再等,主线程终止则所有子线程终止 #################
    # import time
    # def func(arg):
    #     time.sleep(2)
    #     print(arg)
    #
    # t1 = threading.Thread(target=func,args=(3,))
    # t1.setDaemon(True)
    # t1.start()
    #
    # t2 = threading.Thread(target=func,args=(9,))
    # t2.setDaemon(True)
    # t2.start()
    #
    # print(123)
    
    # ###################### 4.开发者可以控制主线程等待子线程(最多等待时间) #################
    # import time
    # def func(arg):
    #     time.sleep(0.01)
    #     print(arg)
    #
    # print('创建子线程t1')
    # t1 = threading.Thread(target=func,args=(3,))
    # t1.start()
    # # 无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走。
    # # 有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续往下走。
    # t1.join(2)
    #
    # print('创建子线程t2')
    # t2 = threading.Thread(target=func,args=(9,))
    # t2.start()
    # t2.join(2) # 让主线程在这里等着,等到子线程t2执行完毕,才可以继续往下走。
    #
    # print(123)
    
    # ###################### 4.线程名称 #################
    # def func(arg):
    #     # 获取当前执行该函数的线程的对象
    #     t = threading.current_thread()
    #     # 根据当前线程对象获取当前线程名称
    #     name = t.getName()
    #     print(name,arg)
    #
    # t1 = threading.Thread(target=func,args=(11,))
    # t1.setName('侯明魏')
    # t1.start()
    #
    # t2 = threading.Thread(target=func,args=(22,))
    # t2.setName('刘宁钱')
    # t2.start()
    #
    # print(123)
    
    # ###################### 5.线程本质 #################
    # 先打印:11?123?
    # def func(arg):
    #     print(arg)
    #
    # t1 = threading.Thread(target=func,args=(11,))
    # t1.start()
    # # start 是开始运行线程吗?不是
    # # start 告诉cpu,我已经准备就绪,你可以调度我了。
    # print(123)
    
    
    # ###################### 6.补充:面向对象版本的多线程 #################
    # 多线程方式:1 (常见)
    # def func(arg):
    #     print(arg)
    #
    # t1 = threading.Thread(target=func,args=(11,))
    # t1.start()
    
    # 多线程方式:2
    # class MyThread(threading.Thread):
    #
    #     def run(self):
    #         print(11111,self._args,self._kwargs)
    #
    # t1 = MyThread(args=(11,))
    # t1.start()
    #
    # t2 = MyThread(args=(22,))
    # t2.start()
    
    print('end')
    线程的使用
    # by luffycity.com
    import threading
    
    
    # ###################### 1.线程的基本使用 #################
    # def func(arg):
    #     print(arg)
    #
    #
    # t = threading.Thread(target=func,args=(11,))
    # t.start()
    #
    #
    # print(123)
    # ###################### 2.主线程默认等子线程执行完毕 #################
    # import time
    # def func(arg):
    #     time.sleep(arg)
    #     print(arg)
    #
    #
    # t1 = threading.Thread(target=func,args=(3,))
    # t1.start()
    #
    # t2 = threading.Thread(target=func,args=(9,))
    # t2.start()
    #
    # print(123)
    # ###################### 3.主线程不再等,主线程终止则所有子线程终止 #################
    # import time
    # def func(arg):
    #     time.sleep(2)
    #     print(arg)
    #
    # t1 = threading.Thread(target=func,args=(3,))
    # t1.setDaemon(True)
    # t1.start()
    #
    # t2 = threading.Thread(target=func,args=(9,))
    # t2.setDaemon(True)
    # t2.start()
    #
    # print(123)
    
    # ###################### 4.开发者可以控制主线程等待子线程(最多等待时间) #################
    # import time
    # def func(arg):
    #     time.sleep(0.01)
    #     print(arg)
    #
    # print('创建子线程t1')
    # t1 = threading.Thread(target=func,args=(3,))
    # t1.start()
    # # 无参数,让主线程在这里等着,等到子线程t1执行完毕,才可以继续往下走。
    # # 有参数,让主线程在这里最多等待n秒,无论是否执行完毕,会继续往下走。
    # t1.join(2)
    #
    # print('创建子线程t2')
    # t2 = threading.Thread(target=func,args=(9,))
    # t2.start()
    # t2.join(2) # 让主线程在这里等着,等到子线程t2执行完毕,才可以继续往下走。
    #
    # print(123)
    
    # ###################### 4.线程名称 #################
    # def func(arg):
    #     # 获取当前执行该函数的线程的对象
    #     t = threading.current_thread()
    #     # 根据当前线程对象获取当前线程名称
    #     name = t.getName()
    #     print(name,arg)
    #
    # t1 = threading.Thread(target=func,args=(11,))
    # t1.setName('侯明魏')
    # t1.start()
    #
    # t2 = threading.Thread(target=func,args=(22,))
    # t2.setName('刘宁钱')
    # t2.start()
    #
    # print(123)
    
    # ###################### 5.线程本质 #################
    # 先打印:11?123?
    # def func(arg):
    #     print(arg)
    #
    # t1 = threading.Thread(target=func,args=(11,))
    # t1.start()
    # # start 是开始运行线程吗?不是
    # # start 告诉cpu,我已经准备就绪,你可以调度我了。
    # print(123)
    
    
    # ###################### 6.补充:面向对象版本的多线程 #################
    # 多线程方式:1 (常见)
    # def func(arg):
    #     print(arg)
    #
    # t1 = threading.Thread(target=func,args=(11,))
    # t1.start()
    
    # 多线程方式:2
    # class MyThread(threading.Thread):
    #
    #     def run(self):
    #         print(11111,self._args,self._kwargs)
    #
    # t1 = MyThread(args=(11,))
    # t1.start()
    #
    # t2 = MyThread(args=(22,))
    # t2.start()
    
    print('end')
    多线程
    # by luffycity.com
    import time
    import threading
    
    lock = threading.RLock()
    
    n = 10
    
    def task(i):
        print('这段代码不加锁',i)
    
        lock.acquire() # 加锁,此区域的代码同一时刻只能有一个线程执行
        global n
        print('当前线程',i,'读取到的n值为:',n)
        n = i
        time.sleep(1)
        print('当前线程',i,'修改n值为:',n)
        lock.release() # 释放锁
    
    
    for i in range(10):
        t = threading.Thread(target=task,args=(i,))
        t.start()
    多线程问题

    暂时忘记知识点

    import sys
    
    v1 = sys.getcheckinterval()
    print(v1)
    查看gil切换指令
    总结:
    1. 应用程序/进程/线程的关系? *****(面试题:进程/线程/协程的区别?)
    
    2. 为什么要创建线程?
        由于线程是cpu工作的最小单元,创建线程可以利用多核优势实现并行操作(Java/C#)。
        注意:线程是为了工作。
        
    3. 为什么要创建进程?
        进程和进程之间做数据隔离(Java/C#)。
        
        注意:进程是为了提供环境让线程工作。
        
    4. Python
       IO操作不占用CPU a. Python中存在一个GIL锁。
    ***** - 造成:多线程无法利用多核优势。 - 解决:开多进程处理(浪费资源) 总结: IO密集型:多线程 计算密集型:多进程 b. 线程的创建 - Thread ***** - MyThread c. 其他 - join ***** - setDeanon ***** - setName ***** - threading.current_thread() ***** d. 锁 - 获得 - 释放
      6、线程创建的越多越好吗?
        不好,效率呈现抛物线形式
        线程之间进行切换时,要做上下文管理(操作费时)
  • 相关阅读:
    jmeter(六)元件的作用域与执行顺序
    通过数据自动生成流程图(前端方向) dagred3
    jmeter(二)录制脚本
    最准的中文文本相似度计算工具
    BERT文本相似度实战
    Jmeter 字符串拼接参数
    常见数据库字段类型与java.sql.Types的对应
    jmeter(二十七)分布式压测注意事项
    词法分析利用Jieba实现高频词提取(Python)
    jmeter(二十一)jmeter常用插件介绍
  • 原文地址:https://www.cnblogs.com/xiaobai686/p/11802712.html
Copyright © 2020-2023  润新知