一:线程理论
1.什么是线程
在传统操作系统中,每个进程用一个地址空间,而且默认就有一个控制线程
线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程。
车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一条流水线
流水线的工作需要电源,电源就相当于CPU
所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说是资源集合),而线程才是CPU上的执行单位。
多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间资源。
2.线程与进程的区别
1.# 线程的创建开销小
2.# 线程共享创建它的进程的namespace,进程有自己的namespace
3.# 线程可以直接访问其进程的数据,而进程拥有自己父进程的数据的副本
4.# 线程是CPU执行单位,而进程是一个资源单位
二:开启线程的两种方式
方式一:导入模块
from threading import Thread
def task():
print('m')
# 创建线程对象
t = Thread(target = task)
# 执行线程
t.start()
方式二:创建类
from threading import Thread
class Mythread(Thread):
def run():
print('子线程任务')
# 创建一个对象
m = Mythread()
# 执行对象
m.start()
三:线程特性介绍
from threading import Thread,current_thread,active_count,enumerate
import time
def task():
print('子进程...')
time.sleep(1)
print(current_thread())
t = Thread(target = task,name ='aaa')
t.daemon = True
print(t.name)
t.start()
print(active_count())
print(enumerate())
print('over')
active_count() # 获取当前活跃线程的数量
enumerate() # 返回活跃的线程对象枚举
t.daemon = True # 守护线程,执行顺序和进程一样
current_thread() # 获取当前线程对象
四:守护线程
无论是进程还是线程,都遵循:守护xxx会等待主xxx运行完毕后被销毁
需要强调的是:运行完毕并非终止运行
from threading import Thread
import time
def sayhi(name):
time.sleep(2)
print('%s say hello' %name)
if __name__ == '__main__':
t = Thread(target = sayhi,args = ('aaa',))
t.setDaemon(True)
t.start()
print('主线程')
print(t.is_alive)
五:线程互斥锁
# 多线程是可以共用同一个进程的数据的,所以在共用这些数据的同时,会产生对数据的竞争,竞争# 带来的就是错乱,所以,我们同样需要用锁,来将这些竞争变得有序
from threading import Thread,Lock
mutex = Lock()
def task1():
mutex.acquire()
for i in range(100):
print('====')
mutex.release()
def task2():
mutex.acquire()
for i in range(100):
print('!!!!!!')
mutex.release()
def task3():
mutex.acquire()
for i in range(100):
print('****')
mutex.release()
t1 = Thread(target=task1)
t2 = Thread(target=task2)
t3 = Thread(target=task3)
t1.start()
t2.start()
t3.start()
六:死锁
from threading import Thread,Lock
import time
mutex1 = Lock()
mutex2 = Lock()
def task():
mutex1.acquire()
print('aaa')
time.sleep(2)
mutex2.acquire()
print('bbb')
mutex2.release()
mutex1.release()
def func():
mutex2.acquire()
print('ccc')
mutex1.acquire()
print('ddd')
time.sleep(2)
mutex1.release()
mutex2.release()
t1 = Thread(target = task)
t2 = Thread(target = func)
t1.start()
t2.start()
print('s')
七:递归锁
from threading import Thread,RLock
mutex = RLock()
def task():
mutex.acquire()
print('aaa')
mutex.acquire()
print('bbb')
t = Thread(target=task)
t.start()
# 如果是mutex=Lock的话,第8行打印不出来,因为第一次锁没有被mutex.release()释放,会# 处于锁死的状态。
八:信号量
from threading import Thread,Semaphore,current_thread,active_count
sm = Semaphore(2)
def task():
sm.acquire()
for i in range(10):
print(current_thread())
time.sleep(0.5)
sm.release()
def task2():
for i in range(10):
print(current_thread())
time.sleep(0.5)
for i in range(5):
Thread(target=task).start()
Thread(target=task2).start()
print(active_count())
# 用于控制 同时执行被锁定代码的线程数量 也就是线程并发数量
# 也是一种锁
九:线程和进程的区别
1.# 进程是一个资源单位,一个进程可以包含多个线程
2.# 多个线程之间可以共享区域
3.# 线程启动的消耗的资源较小