分配资源的基本单位,一旦创建一个进程就会分配一定的资源。

线程是cpu调度的基本单位,每个进程,每个进程至少都有一个线程,而这个线程就是我们通常说的主线程

线程之间数据可以共享,进程之间数据相互隔离(注:这里的线程应该是一个进程内的线程之间)


import threading
import time

def music(name,num):
    for i in range(1,num):
        time.sleep(0.1)#模拟耗时操作
        print(f'{name}听第{i}遍音乐中!')
def coding(name,num):
    for i in range(1,num):
        time.sleep(0.1)
        print(f'{name}编写第{i}遍代码中...')


if __name__ == '__main__':
    t1=threading.Thread(target=music,args=('kkk',11))
    t2=threading.Thread(target=coding,kwargs={'name':'sss','num':11})
    for i range(5):#t1,t2未启动不会争抢
        print("main启动")
    t1.start()
    t2.start()

线程的注意点

1,线程之间执行是无序的(原因:下面的CPU调度资源策略)

2,主线程会等待所有的子线程执行结束再结束

和守护进程类似,thread(target=show, daemon=True)或者t1.setDaemon(True)

3,线程之间会共享全局变量

4,多线程之间共享全局变量数据会出现错误问题,可以用互斥锁解决

出错原因:当线程1在使用全局变量时,线程2也在使用,当一返回值时,二也返回,但这样就造成了返回了两次但只造成一次数值变换

解决:线程同步,保证同一时刻只有一个线程去操作全局变量

同步:就是协同步调,按预定的先后次序进行运行

import threading
import time

global_num=0
def sum_func1():
    global global_num
    for i in range(1000000):
        global_num+=1
    print(f"sum_func1的执行结果为{global_num}")

def sum_func2():
    global global_num
    for i in range(1000000):
        global_num+=1
    print(f"sum_func2的执行结果为{global_num}")

if __name__ == '__main__':
    t1=threading.Thread(target=sum_func1)
    t2=threading.Thread(target=sum_func2)
    t1.start()
    t2.start()
sum_func1的执行结果为1314943
sum_func2的执行结果为2000000

CPU调度资源的策略:

1,均分时间片(可能会导致资源闲置,即可能不需要资源的线程也分到一部分资源)

2,抢占式调度(谁要谁就去抢资源)

互斥锁:共享数据进行锁定

死锁:一直等待对方释放锁的情景

产生原因:未在合适地方释放锁

结果:程序无法执行下去

import threading
mutex=threading.Lock()
global_num=0
def sum_func1():
    mutex.acquire()
    global global_num
    for i in range(1000000):
        global_num+=1
    print(f"sum_func1的执行结果为{global_num}")
    mutex.release()

def sum_func2():
    mutex.acquire()
    global global_num
    for i in range(1000000):
        global_num+=1
    print(f"sum_func2的执行结果为{global_num}")
    mutex.release()

if __name__ == '__main__':
    t1=threading.Thread(target=sum_func1)
    t2=threading.Thread(target=sum_func2)
    t1.start()
    t2.start()

创建,上锁,释放锁

threading.Lock();mutex.acquire();mutex.release()

使用互斥锁时可能会导致死锁或者锁不住

线程进程对比

线程依赖进程,进程时CPU分配资源的基本单位,线程是CPU调度资源的基本单位

进程更消耗资源,不能共享全局变量,相对更稳定

线程更轻量级,可以共享全局变量,相对更灵活