zoukankan      html  css  js  c++  java
  • 线程

    1.线程定义

    线程是操作系统调度的最小单位
    它被包含在进程之中,是进程中的实际运作单位
    进程本身是无法自己执行的,要操作CPU,必须创建一个线程,线程是一系列指令的集合
    

    线程定义拓展回答内容

    1.线程操作系统能够进行运行调度的最小单位,它被包含在进程之中,是进程中的实际运作单位
    
    2.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
    
    3.无论你启多少个线程,你有多少个CPU,python在执行的时候会淡定的在同一时刻只允许一个线程允许
    
    4.进程本身是无法自己执行的,要操作cpu,必须创建一个线程,线程是一系列指令的集合
    
    5. 所有在同一个进程里的线程是共享同一块内存空间的,不同进程间内存空间不同
    
    6. 同一个进程中的各线程可以相互访问资源,线程可以操作同进程中的其他线程,但进程仅能操作子进程
    
    7. 两个进程想通信,必须要通过一个中间代理
    
    8. 对主线程的修改可能回影响其他子线程,对主进程修改不会影响其他进程因为进程间内存相互独立,但是同一进程下的线程共享内存
    

    2.进程和线程的区别

    1.进程包含线程
    
    2.线程共享内存空间
    
    3.进程内存是独立的(不可互相访问)
    
    4.进程可以生成子进程,子进程之间互相不能互相访问(相当于在父级克隆两个子进程)
    
    5.在一个进程里面线程之间可以互相交流,两个进程想通信,必须通过一个中间代理来实现。
    
    6.创建新线程很简单,创建进程需要对其父类进行克隆
    
    7.一个线程可以控制或操作同一个进程里面的其他线程。但进程只能操作子进程。
    
    8.对于线程的修改,可能会影响到其他线程的行为。但是对于父进程的修改不会影响到子进程。
    

    3.for循环同时启动多个线程

    import threading
    import time
    
    def sayhi(num): #定义每个线程要运行的函数
        print("running on number:%s" %num)
        time.sleep(3)
    for i in range(50):
        t = threading.Thread(target=sayhi,args=('t-%s'%i,))
        t.start()
    

    4. t.join(): 实现所有线程都执行结束后再执行主线程

    import threading
    import time
    start_time = time.time()
    
    def sayhi(num): #定义每个线程要运行的函数
        print("running on number:%s" %num)
        time.sleep(3)
    t_objs = []    #将进程实例对象存储在这个列表中
    for i in range(50):
        t = threading.Thread(target=sayhi,args=('t-%s'%i,))
        t.start()          #启动一个线程,程序不会阻塞
        t_objs.append(t)
    print(threading.active_count())    #打印当前活跃进程数量
    for t in t_objs: #利用for循环等待上面50个进程全部结束
        t.join()     #阻塞某个程序
    print(threading.current_thread())    #打印执行这个命令进程
    
    print("----------------all threads has finished.....")
    print(threading.active_count())
    print('cost time:',time.time() - start_time)
    

    5. setDaemon(): 守护线程,主线程退出时,需要子线程随主线程退出

    import threading
    import time
    start_time = time.time()
    
    def sayhi(num): #定义每个线程要运行的函数
        print("running on number:%s" %num)
        time.sleep(3)
    for i in range(50):
        t = threading.Thread(target=sayhi,args=('t-%s'%i,))
        t.setDaemon(True)  #把当前线程变成守护线程,必须在t.start()前设置
        t.start()          #启动一个线程,程序不会阻塞
    print('cost time:',time.time() - start_time)
    

    6. GIL全局解释器锁:保证同一时间仅有一个线程对资源有操作权限

    作用:在一个进程内,同一时刻只能有一个线程执行
    
    说明:python多线程中GIL锁只是在CPU操作时(如:计算)才是串行的,其他都是并行的,所以比串行快很多
    
    1)为了解决不同线程同时访问同一资源时,数据保护问题,而产生了GIL
    
    2)GIL在解释器的层面限制了程序在同一时间只有一个线程被CPU实际执行,而不管你的程序里实际开了多少条线程
    
    3)为了解决这个问题,CPython自己定义了一个全局解释器锁,同一时间仅仅有一个线程可以拿到这个数据
    
    4)python之所以会产生这种不好的状况是因为python启用一个线程是调用操作系统原生线程,就是C接口
    
    5)但是这仅仅是CPython这个版本的问题,在PyPy,中就没有这种缺陷
    

    7. 线程锁

    1)当一个线程对某个资源进行CPU计算的操作时加一个线程锁,只有当前线程计算完成主动释放锁,其他线程才能对其操作
    2)这样就可以防止还未计算完成,释放GIL锁后其他线程对这个资源操作导致混乱问题
    
    用户锁使用举例
    import time
    import threading
    lock = threading.Lock()          #1 生成全局锁
    def addNum():
        global num                  #2 在每个线程中都获取这个全局变量
        print('--get num:',num )
        time.sleep(1)
        lock.acquire()              #3 修改数据前加锁
        num  -= 1                   #4 对此公共变量进行-1操作
        lock.release()              #5 修改后释放
    

    8. Semaphore(信号量)

    1. 互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据
    
    2. 比如一个餐厅只有三个桌椅,那最多只允许3个人吃饭,后面的人只能等里面有人出来了才能再进去
    
    3. 作用就是同一时刻允许运行的线程数量
    

    9. 线程池实现并发

    import requests
    from concurrent.futures import ThreadPoolExecutor
    
    def fetch_request(url):
        result = requests.get(url)
        print(result.text)
    
    url_list = [
        'https://www.baidu.com',
        'https://www.google.com/',         #google页面会卡住,知道页面超时后这个进程才结束
        'http://dig.chouti.com/',          #chouti页面内容会直接返回,不会等待Google页面的返回
    ]
    
    pool = ThreadPoolExecutor(10)            # 创建一个线程池,最多开10个线程
    for url in url_list:
        pool.submit(fetch_request,url)       # 去线程池中获取一个线程,线程去执行fetch_request方法
    
    pool.shutdown(True)                      # 主线程自己关闭,让子线程自己拿任务执行
    
  • 相关阅读:
    sql优化
    一些有用的单词(1)
    用到的 Sed 注解
    终端工具注册码
    nginx四层、七层负载均衡配置示例
    http 状态码
    04. Golang 数据类型
    03. Golang 特性
    02. Go 命令
    01. GOPATH 目录结构划分的两种风格
  • 原文地址:https://www.cnblogs.com/wonderlandlove/p/12815339.html
Copyright © 2011-2022 走看看