线程

线程被称作轻量级的进程。  GIL:全局解释锁(只有Cpython解释器才有)
                                         线程会被强迫放弃CPU的因素
                                            (线程会受时间片影响)(GIL会限制每个线程的执行时间,一般是5毫秒)(或者限制线程执行固定数量的字节码)
                                    对于线程来说,因为有了GIL,所以没有真正的并行

          计算机的执行单位以线程为单位。计算机的最小可执行是线程。
          进程是资源分配的基本单位。线程是可执行的基本单位,是可被调度的基本单位。
          线程不可以自己独立拥有资源。线程的执行,必须依赖于所属进程中的资源。
          进程中必须至少应该有一个线程。

          线程又分为用户级线程和内核级线程(了解)
            用户级线程:对于程序员来说的,这样的线程完全被程序员控制执行,调度
            内核级线程:对于计算机内核来说的,这样的线程完全被内核控制调度。

      进程由 代码段  数据段  PCB组成(process control block)
      线程由 代码段  数据段  TCB组成(thread control block)
      
#模块:threading
#导入方法:from threading import Thread

#线程和进程的比较
          thread - 线程
          import thread 操作线程的模块
          import threading 用这个去操作线程
         (1) cpu切换进程要比cpu切换线程 慢很多
             在python中,如果IO操作过多的话,使用多线程最好了
         (2) 在同一个进程内,所有线程共享这个进程的pid,也就是说所有线程共享所属进程的所有资源和内存地址
         (3) 在同一个进程内,所有线程共享该进程中的全局变量

         (4) 因为有GIL锁的存在,在Cpython中,没有真正的线程并行。但是有真正的多进程并行
             当你的任务是计算密集的情况下,使用多进程好
            总结:在CPython中,IO密集用多线程,计算密集用多进程

        (5)关于守护线程和守护进程的事情(注意:代码执行结束并不代表程序结束)
            守护进程:要么自己正常结束,要么根据父进程的代码执行结束而结束
            守护线程:要么自己正常结束,要么根据父线程的执行结束而结束       
       
#线程方法:
        (1)锁机制
             递归锁
                 RLock()    可以有无止尽的锁,但是会有一把万能钥匙
             互斥锁:
                 Lock()     一把钥匙配一把锁
             GIL:全局解释器锁
                锁的是线程,是CPython解释器上的一个锁,锁的是线程,意思是在同一时间只允许一个线程访问cpu
        (2) 信号量:
            from threading import Semaphore
            去看多进程的信号量

        (3) 事件
            from threading import Event
            去看多进程的事件机制

        (4) 条件
            from threading import Condition
            条件是让程序员自行去调度线程的一个机制
            # Condition涉及4个方法
            # acquire()
            # release()
            # wait()    是指让线程阻塞住
            # notify(int)  是指给wait发一个信号,让wait变成不阻塞
            #     int是指,你要给多少给wait发信号
5) 定时器
            from threading import Timer
                # Timer(time,func)
                # time:睡眠的时间,以秒为单位
                # func:睡眠时间之后,需要执行的任务

#基本使用方法:
import threading
from threading import Thread
import time
################################# 常规方法
# def func():
#     print('这是一个子线程')
#     time.sleep(2)
#
# if __name__ == '__main__':
#     t = Thread(target=func,args=())
#     t.start()


#################################类的方法


# class MyThread(Thread):
#     def __init__(self):
#         super(MyThread, self).__init__()
#     def run(self):
#         print('我是一个子线程')
#
# t = MyThread()
# t.start()
模块:Condition
导入方法:from threading import Condition,Thread
模块方法:con=Condition()
    #con.acquire()
    #con.release()
    #con.wait()  # 假设有一个初始状态为False,阻塞。一旦接受到notify的信号后,变为True,不再阻塞
    #con.notify(int)  给wait发信号,发int个信号,会传递给int个wait,让int个线程正常执行
    
注意事项:
    同一个线程内,递归锁可以多次acquire,但互斥锁不可以
    不同线程,递归锁是保证只能一个线程用,并多次acquire,其他线程等待

#例子
from threading import Condition,Thread
import time

def func(con,i):
    con.acquire()# 主线程和10个子线程都在抢夺递归锁的一把钥匙。
    # 如果主线程抢到钥匙,主线程执行while 1,input,然后notify发信号,还钥匙。但是,此时如果主线程执行特别快
    # 极有可能接下来主线程又会拿到钥匙,那么此时哪怕其他10个子线程的wait接收到信号,但是因为没有拿到钥匙,所以其他子线程还是不会执行
    con.wait()
    print('第%s个线程执行了'%i)
    con.release()

con = Condition()
for i in range(10):
    t = Thread(target=func,args = (con,i))
    t.start()
while 1:
    # print(123)
    con.acquire()
    num = input('>>>')
    con.notify(int(num))
    con.release()
    time.sleep(0.5)
原文地址:https://www.cnblogs.com/god-for-speed/p/11719102.html