文章目录
一、线程
1.概念
- 线程是进程中执行的一个分支
- 线程是依附在进程中
- 线程是CPU调度的基本单位
- 作用:能够实现多任务
2.导入threading模块
3.使用方法和进程相似
- 创建线程对象:thread = threading.Thread(target=)
- 启动线程:thread.start()
4.注意点
- 线程,进程的执行是无序的
循环创建多个线程,start后,都会处于就绪态,cpu调度哪个线程,哪个线程就会执行
def func():
time.sleep(1)
print('当前线程为:', threading.current_thread().name)
if __name__ == '__main__':
for i in range(5):
thread = threading.Thread(target=func)
thread.start()
- 主线程会等待所有的子线程执行结束在结束
def func():
#print('当前线程为:', threading.current_thread().name)
for i in range(5):
print(i)
time.sleep(0.5)
print('子over')
if __name__ == '__main__':
thread = threading.Thread(target=func)
thread.start()
time.sleep(1)
print('主over')
让子线程在主线程结束后就结束的三种方法
- thread = threading.Thread(target=func,daemon= True)
- thread.daemon = True
- thread.setDaemon(True)
- 线程之间共享全局变量(与进程不同)
- 线程之间共享全局变量数据会出问题
解决办法:
线程同步:保证同一时刻只能有一个线程取操作全局变量。同步:就是协同步调,按预定的先后次序进行运行。
- join()
- 互斥锁
5.互斥锁
互斥锁:对共享数据进行锁定,保证同一时刻只能有一个线程操作,保护共享数据
- 生成互斥锁:mutex = threading.Lock()
- 开启锁:mutex.acquire()
- 释放锁:mutex.release()
mutex = threading.Lock()
g_num = 0
def task():
global g_num
for i in range(1000000):
mutex.acquire()
g_num += 1
mutex.release()
print(threading.current_thread().name,g_num)
def task1():
global g_num
mutex.acquire()
for i in range(1000000):
g_num += 1
mutex.release()
print(threading.current_thread().name,g_num)
if __name__ =='__main__':
thread1 = threading.Thread(target=task1)
thread2 = threading.Thread(target=task)
thread1.start()
thread2.start()
6.死锁的解决
g_list = [1,2,3,4]
mutex = threading.Lock()
def func(index):
mutex.acquire()
if index >= len(g_list):
print(threading.current_thread().name,'越界')
mutex.release()# 重点
return
print(threading.current_thread().name, g_list[index])
mutex.release()
if __name__ == '__main__':
for i in range(10):
thread_1 = threading.Thread(target=func , args=(i,))
thread_1.start()
二、多任务
1.概念
多任务:一个时间段执行多个任务(程序)
2.执行方式
并发:交替执行(单核cpu一定是并发)
并行:在多核cpu中,多个任务在多个cpu上同时执行
一般来说并发和并行都是存在的,由操作系统自动调用
三、进程与线程对比
使用场景
- 进程:计算密集型程序(大量的数学计算)
- 线程:适合IO密集型程序(爬虫,读写操作)
四、GIL全局解释器锁
1.特性
GIL保证同一时间,只有一个线程使用CPU
一个进程有一个GIL锁
GIL是Cpython解释器的概念,历史遗留问题
2.释放时间(不用控制)
- 当前线程执行超时会自动释放
- 当前线程阻塞时会自动释放
- 执行完成时
3.弊端
对计算密集型程序会影响,占用系统资源
对IO密集型影响不大(大量时间在等待,一个或者多个等待影响不大)