• 线程


    线程理论

      什么是线程:指令的执行过程。

            在进程中存在线程,进程如果没有线程无法运行,进程只是负责提供内存资源,线程真正进入CPU,是CPU最小的运行单位。多线程就是为了一个进程执行多个任务。

            线程的创建销毁被进程快,且不像进程那样内存隔离,可以不需要额外操作就可以实现数据共享。

            并发的时候,多进程加多线程;多核中也可以应用多线程。

    线程的两种创建方式(重点)main可写可不写

     1 from threading import Thread
     2 第一种
     3 def f1(n):
     4     print(1+n)
     5 
     6 def f2(n):
     7     print(2)
     8 
     9 if __name__ == '__main__':
    10     t1 = Thread(target=f1,args=(0,))  #与进程创建相同
    11     t2 = Thread(target=f2,args=(0,))  #与进程创建相同
    12     t1.start()
    13     t2.start()
    14 print('主线程')
    15 第二种
    16 class MyThread(Thread):
    17     def __init__(self,name):
    18         super().__init__()
    19         self.name = name
    20 
    21     def run(self):
    22         print(self.name)
    23 
    24 if __name__ == '__main__':
    25     t= MyThread('cc')
    26     t.start()
    27     print('主线程')
    线程的两种创建方式

    查看线程pid线程(了解)

      os.getpid(),显示都是同一个进程号

    线程可以直接数据共享             等待线程执行完毕的方法为join(),用法同进程

    与进程效率对比      创建时间差了将近百倍

    线程空间不是隔离的

      Io密集型切换提高代码效率;计算密集型切换降低代码效率。

      计算密集型,运行时间加长,此时多线程无法应用多核技术,所有多线程此时反而比多进程慢

    守护线程

      守护线程等待所有非守护线程结束才结束,一旦别人都结束,而守护进程没结束的话也自杀

      进程只守护主进程

    线程锁/互锁(重点)

     1 from threading import Lock,Thread
     2 import time
     3 
     4 num = 100
     5 def f1():
     6     global num
     7     temp = num
     8     temp -= 1
     9     time.sleep(1)
    10     num = temp
    11 
    12 if __name__ == '__main__':
    13     t_list = []
    14 
    15     for i in range(10):
    16         t = Thread(target=f1,)
    17         t.start()
    18         t_list.append(t)
    19 
    20     [t.join() for tt in t_list]
    21 
    22     print('主线程的num:',num)
    23 此时无法得到90,十个线程的操作在相同,瞬间开启,
    24 每个人线程拿到的temp可能都是100,最后赋值回去为99,可能是拿到99,变成了99
    25 
    26 num = 100
    27 
    28 
    29 def f1(loc):
    30     global num   #只是声明一个变量,不会拿到数据,不存在赋值
    31     loc.acquire()
    32     temp = num
    33     temp -= 1
    34     time.sleep(0.1)
    35     num = temp
    36     loc.release()
    37 
    38 
    39 if __name__ == '__main__':
    40     t_list = []
    41     t_loc = Lock()
    42     for i in range(10):
    43         t = Thread(target=f1,args=(t_loc,) )
    44         t.start()
    45         t_list.append(t)
    46 
    47     [t.join() for tt in t_list]
    48 
    49     print('主线程的num:', num)
    50 
    51     #加锁,用法同进程锁
    线程锁

    死锁(重点)

      在锁的代码中再完成地嵌套一个锁时发生,

      A中嵌套一个完整的B,B中嵌套一个完整的A,两个在想抢对方已有的锁的时候都会卡死,相互锁死

    递归锁(重点)

      破除死锁,同一把锁多个形式,RLock()

      内含计数器,创建一次就加一,释放一个就减一,为零才可以抢

    GIL锁:

      在全局的cpython解释器上加的一把锁

      解释器用于解释自己的代码为二进制
           同一时间,只能有一个线程可以进入cpython解释器,导致py不能使用多核技术。想多线程并发依旧是可以搞的,但是就需要开多进程来实现了,因为就是又多开了一个解释器。
            线程可以节约io密集型程序的时间,计算密集型则不行。一般进程按照cpu的个数开。
      子进程不能input,因为输入台只能由主进程使用,输出内容各个进程都可以,但是并发输出可能会打印混乱。 子线程可以输入,因为同属一个进程。

  • 相关阅读:
    Mac卸载vue-cli2X 时失败: Missing write access to --如侦探小说般的解谜之路
    mac-coursera网站DNS污染的解决方案
    mac摄像头打不开的问题
    node-npm-webpack
    webpack报错 : Can't resolve '.distundle.js'
    npm Error: listen EADDRINUSE 127.0.0.1:8080
    常用mac终端命令
    mac下的环境变量配置- cnpm :command not found
    less安装 出错问题
    vue-devtools vue开发调试神器
  • 原文地址:https://www.cnblogs.com/shachengcc1/p/11337214.html
Copyright © 2020-2023  润新知