目录
线程
什么是线程
- 是系统分配给处理器时间资源的基本单位,或者说进程之内独立执行的一个单元执行流
特点
- 程序执行的最小单位
为什么需要线程
- 进程在同一时段只能做一件事情,如果想做很多事情,就会有些困难
- 进程在执行中遭遇阻塞,那么整个进程就会挂起
如何开启线程
#方式一
from threading import Thread
import time
###线程开启的第一种方式
def mythred():
print('线程开启')
time.sleep(5)
print('线程结束')
#线程中可加可不加
if __name__ == '__main__':
t = Thread(target = mythred)
t.start()
#####方式二
from threading import Thread
import time
#通过类继承额方法
class Mythred(Thread):
def run(self):
print('线程开启')
time.sleep(5)
print('线程结束')
t = Mythred()
t.start()
线程创建速度vs进程创建速度
from threading import Thread
from multiprocessing import Process
import time
def task(name):
print(f'{name} is running')
time.sleep(2)
print(f'{name} is end')
if __name__ == '__main__':
t = Thread(target=task,args=('子线程',))
p = Process(target=task,args=('子进程',))
# t.start()
p.start()
print('主')
'''
开启子线程的打印效果:
子线程 is running
主
子线程 is end
开启子进程打印效果:
主
子进程 is running
子进程 is end
进程和线程的创建速度
开启子进程需要申请资源开辟空间 慢
开启子线程只是告诉操作系统一个执行方案 快
'''
线程的join方法
线程的join方法使用起来与进程的join方法相同
from threading import Thread
import time
def task():
print('子线程 start')
time.sleep(2)
print('子线程 end')
t = Thread(target=task)
t.start()
t.join() # 等待子线程运行结束
print('主线程')
守护线程
# 守护线程 守护的是进程的运行周期
from threading import Thread,enumerate,currentThread
import time
def task():
print('守护线程开始')
print(currentThread())
time.sleep(20)
# print('守护线程结束')
def task2():
print('子线程 start')
time.sleep(5)
print(enumerate())
print('子线程 end')
if __name__ == '__main__':
t1 = Thread(target=task)
t2 = Thread(target=task2)
t1.daemon = True
t2.start()
t1.start()
print('主')
线程锁的安全问题
from threading import Thread,Lock
x = 0
def task():
global x
for i in range(100000):
x += 1
t1 = Thread(target=task)
t2 = Thread(target=task)
t3 = Thread(target=task)
t1.start()
t2.start()
t3.start()
print(x)
228891
上述代码我们发现,本应该为300000的x值发生了偏差。
解决方法
from threading import Thread,Lock
x = 0
lock = Lock()
def task():
global x
lock.acquire()
for i in range(200000):
x += 1
lock.release()
t1 = Thread(target=task)
t2 = Thread(target=task)
t3 = Thread(target=task)
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print(x)
线程死锁问题
所谓死锁
- 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
from threading import Thread,Lock
lock1 = Lock()
lock2 = Lock()
import time
class Mythread(Thread):
def run(self):
self.task1()
self.task2()
def task1(self):
lock1.acquire()
print(f'{self.name}抢到了锁一')
lock2.acquire()
print(f'{self.name}抢到了锁二')
lock2.release()
print(f'{self.name}释放掉了锁二')
lock1.release()
print(f'{self.name}释放掉了锁一')
def task2(self):
lock2.acquire()
print(f'{self.name}抢到了锁二')
for i in range(3):
t = Mythread()
t.start()
递归锁(用于解决死锁问题)
from threading import Thread,Lock,RLock
# 递归锁 在同一个线程内可以被多次acquire
# 如何释放 内部相当于维护了一个计数器 也就是说同一个线程 acquire了几次就要release几次
mutex1 = RLock()
mutex2 = mutex1
import time
class MyThreada(Thread):
def run(self):
self.task1()
self.task2()
def task1(self):
mutex1.acquire()
print(f'{self.name} 抢到了 锁1 ')
print(f'{self.name} 释放了 锁1 ')
def task2(self):
mutex1.acquire()
print(f'{self.name} 抢到了 锁1 ')
mutex1.release()
print(f'{self.name} 释放了 锁1 ')
for i in range(3):
t = MyThreada()
t.start()
信号量
含义:
- 一个进程向另一个进程发送一个信号来传递某种信息,接收者根据接收到的信号进行相应的行为
使用threading模块里的Semaphore类实现了信号量对象
from threading import Thread,currentThread,Semaphore
import time
def task():
sm.acquire()
print(f'{currentThread().name} 在执行')
time.sleep(3)
sm.release()
sm = Semaphore(5)
for i in range(15):
t = Thread(target=task)
t.start()