文章目录
1.进程
进程是资源分配的最小单位,线程是CPU调度的最小单位。每一个进程中至少有一个线程。
主进程中的线程称为主线程,其他开启的线程称为子线程
# 如何开启线程
from multiprocessing import Process
from threading import Thread
def task():
print("子线程")
if __name__ == '__main__':
t = Thread(target=task)
t.start()
print("主线程")
2.全局解释器锁(GIL)
1. python代码在解释器中执行,cpython解释器, pypy解释器
2. GIL锁在解释器中存在,他只在cpython解释器中,pypy解释器中不存在
3. 起一个垃圾回收线程,起一个正常执行的线程,垃圾回收还没回收完毕,另一个线程可能会抢占资源
4. 设置了一把全局解释器锁(GIL锁),有了这把锁,就保证同一时刻,只能有一个线程执行,
只要线程想执行,那么,就必须拿到这把GIL锁
5. 如果是io密集型:选择线程
6. 如果是计算密集型:选择进程
3.线程与进程的区别
可以归纳为以下4点:
- 地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
- 通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
- 调度和切换:线程上下文切换比进程上下文切换要快得多。
- 在多线程操作系统中,进程不是一个可执行的实体。
4.通过threading.Thread类创建线程
1. 创建线程的方式一
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=('nick',))
t.start()
print('主线程')
2. 创建线程的方式二
from threading import Thread
import time
class Sayhi(Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
time.sleep(2)
print('%s say hello' % self.name)
if __name__ == '__main__':
t = Sayhi('nick')
t.start()
print('主线程')
Thread类的其他方法
hread实例对象的方法:
isAlive():返回线程是否活动的。
getName():返回线程名。
setName():设置线程名。
threading模块提供的一些方法:
threading.currentThread():返回当前的线程变量。
threading.enumerate():返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount():返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
5.守护线程
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=('nick',))
t.setDaemon(True) # 必须在t.start()之前设置
t.start()
print('主线程')
print(t.is_alive())
'''
主线程
True
'''
6.互斥锁(同步锁)
from threading import Thread,Lock
import time
def task(lock):
global n
lock.acquire() #加锁
temp = n
time.sleep(1)
n = temp - 1
# n -= 1
lock.release() #解锁
if __name__ == '__main__':
n = 10
l = []
lock = Lock()
for i in range(10):
t = Thread(target=task, args=(lock, ) )
t.start()
l.append(t)
for j in l:
j.join()
print(n)
7.信号量
from threading import Thread, Semaphore
from multiprocessing import Process, Lock
# Semaphore:信号量可以理解为多把锁,同时允许多个线程来更改数据
import time, random
sm = Semaphore(2)
def task(i):
sm.acquire()
print("线程:%s,进来了" % i)
time.sleep(random.randint(1, 3))
print("线程:%s,出去了" % i)
sm.release()
if __name__ == '__main__':
for i in range(6):
t = Thread(target=task, args=(i,))
t.start()
8.Event事件
一些线程需要等到其他线程执行完成之后才能执行,类似于发射信号
比如一个线程等待另一个线程执行结束再继续执行
from threading import Thread,Event
import time
event=Event()
def girl(name):
print('%s 还在谈着恋爱'%name)
time.sleep(3)
event.set()
print('%s 单身了'%name)
def boy(name):
print('%s 等着女神分手'%name)
event.wait()
print('女神分手了,%s开始追'%name)
if __name__ == '__main__':
t=Thread(target=girl,args=('刘亦菲',))
t.start()
for i in range(5):
t=Thread(target=boy,args=('屌丝男%s号'%i,))
t.start()