1.多线程
1)特点:
线程的并发是利用cpu上下文的切换(是并发,不是并行)
多线程执行的顺序是无序的
多线程共享全局变量
线程是继承在进程里的,没有进程就没有线程
GIL全局解释器锁
只要在进行耗时的IO操作的时候,能释放GIL,所以只要在IO密集型的代码里,用多线程就很合适
2)多任务处理实例
import threading
global_num = 0
lock = threading.Lock()
def test1():
global global_num
lock.acquire() 保证在该进程执行期间其他进程无法调用num变量
for i in range(1000000):
global_num += 1
lock.release()
def test2():
global global_num
lock.acquire()
for i in range(1000000):
global_num += 1
lock.release()
t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
t1.start()
t2.start()
t1.join() 保证两个子进程执行完成后再执行主进程
t2.join()
print(global_num)
输出结果:
2000000
2.多进程
1)特点
一个程序运行起来之后,代码+用到的资源称之为进程,它是操作系统分配资源的基本单位,不仅可以通过线程完成多任务,进程也是可以的
进程之间是相互独立的
cpu密集的时候适合用多进程
进程之间的资源不共享
2)多任务处理实例
import time
import threading
g_num = 0
def edit():
global g_num
for i in range(10):
g_num += 1
def reader():
print(g_num)
if __name__ == '__main__':
p1 = multiprocessing.Process(target=edit)
p2 = multiprocessing.Process(target=reader())
p1.start()
p2.start()
p1.join()
p2.join()
输出结果:
10
0
3)进程池
import multiprocessing
import time
from multiprocessing import Pool
def test1():
for i in range(10):
time.sleep(1)
print('task1',i)
def test2():
for i in range(10):
time.sleep(1)
print('task2',i)
if __name__ == '__main__':
pool = Pool(2)允许最大同时执行的进程数
pool.apply_async(test1)
pool.apply_async(test2)
pool.close()
pool.join()
输出结果:
task1 0
task2 0
task1 1
task2 1
task1 2
task2 2
task1 3
task2 3
3.协程
1)特点
协程:也叫微线程,协程是在一个线程里面的
异步IO:遇到io请求就切换
先有进程,再有线程,才能有协程
2)多任务处理实例
import time
import gevent
from gevent import monkey
monkey.patch_all()
def test1(n):
for i in range(n):
# gevent.sleep(1)
time.sleep(1)
print('task1',i)
def test2(n):
for i in range(n):
# gevent.sleep(1)
time.sleep(1)
print('task2',i)
g1 = gevent.spawn(test1,10)
g2 = gevent.spawn(test2,10)
g1.join()
g2.join()
输出结果:
task1 0
task2 0
task1 1
task2 1
task1 2
task2 2
task1 3
task2 3