进程是资源分配的最小单位
如果说进程和进程之间相当于程序与程序之间的关系,那么线程与线程之间就相当于程序内的任务和任务之间的关系。所以线程是依赖于进程的,也称为 「微进程」 。它是 程序执行过程中的最小单元 。
进程是CPU资源分配的基本单位,线程是独立运行和独立调度的基本单位(CPU上真正运行的是线程)。进程拥有自己的资源空间,一个进程包含若干个线程,线程与CPU资源分配无关,多个线程共享同一进程内的资源。线程的调度与切换比进程快很多。
CPU密集型代码(各种循环处理、计算等等):使用多进程。IO密集型代码(文件处理、网络爬虫等):使用多线程
线程
python3内置两个thread模块:
_thread模块
threading模块
推荐使用threading模块
1.数据共享,线程同步
如果多个线程共同对某个数据修改,则可能产生混乱结果,为了保证数据的正确性,需要对多个线程进行同步。使用 Thread 对象的 Lock 或 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。
示例代码:
#!/usr/bin/env python3
import time, threading
var = 0
lock = threading.Lock()
def change_it(n):
# 设为全局共享变量
global var
var = var + n
var = var - n
def run_thread(n):
for i in range(3):
# 先要获取锁:
lock.acquire()
change_it(n)
# 改完了一定要释放锁:
lock.release()
t1 = threading.Thread(target=run_thread, args=(5,)) # 逗号不能省!
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
2.线程阻塞
threading.Event为事件处理的机制,全局定义了一个“Flag”:
如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞;
如果“Flag”值为True,那么执行event.wait 方法时便不再阻塞。
clear:将“Flag”设置为False
set:将“Flag”设置为True
用 threading.Event 实现线程间通信,*可以使一个线程等待其他线程的通知,我们把这个Event传递到线程对象中,Event默认内置了一个标志,初始值为False。一旦该线程通过wait()方法进入等待状态,直到另一个线程调用该Event的set()方法将内置标志设置为True时,该Event会通知所有等待状态的线程恢复运行。
示例代码:
import threading, time
import random
def light():
if not event.isSet(): #初始化evet的flag为真
event.set() #wait就不阻塞 #绿灯状态
count = 0
while True:
if count < 10:
print('\033[42;1m---green light on---\033[0m')
elif count < 13:
print('\033[43;1m---yellow light on---\033[0m')
elif count < 20:
if event.isSet():
event.clear()
print('\033[41;1m---red light on---\033[0m')
else:
count = 0
event.set() #打开绿灯
time.sleep(1)
count += 1
def car(n):
while 1:
time.sleep(random.randrange(3, 10))
#print(event.isSet())
if event.isSet():
print("car [%s] is running..." % n)
else:
print('car [%s] is waiting for the red light...' % n)
event.wait() #红灯状态下调用wait方法阻塞,汽车等待状态
if __name__ == '__main__':
car_list = ['BMW', 'AUDI', 'SANTANA']
event = threading.Event()
Light = threading.Thread(target=light)
Light.start()
for i in car_list:
t = threading.Thread(target=car, args=(i,))
t.start()
- threading.active_count()
返回当前存活的线程对象的数量;通过计算len(threading.enumerate())长度而来
import threading, time
def run():
thread = threading.current_thread()
print('%s is running...'% thread.getName()) #返回线程名称
time.sleep(10) #休眠10S方便统计存活线程数量
if __name__ == '__main__':
#print('The current number of threads is: %s' % threading.active_count())
for i in range(10):
print('The current number of threads is: %s' % threading.active_count()) #返回当前存活线程数量
thread_alive = threading.Thread(target=run, name='Thread-***%s***' % i)
thread_alive.start()
thread_alive.join()
print('\n%s thread is done...'% threading.current_thread().getName())
- threading.get_ident()
返回线程pid
import threading, time
def run(n):
print('-'*30)
print("Pid is :%s" % threading.get_ident()) # 返回线程pid
if __name__ == '__main__':
threading.main_thread().setName('Chengd---python') #自定义线程名
for i in range(3):
thread_alive = threading.Thread(target=run, args=(i,))
thread_alive.start()
thread_alive.join()
print('\n%s thread is done...'% threading.current_thread().getName()) #获取线程名
进程
- os.fork()(非win)
- multiprocessing(win)
进程间通信
- 写文件
- redis
- 共享内存
协程
def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK'
def produce(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close()
c = consumer()
produce(c)
网友评论