一、.同步与异步,指结果的返回方式:
同步,是所有的操作都做完,才返回结果。
异步,不用等所有操作都做完,即时返回结果。
二、.多进程与多线程的区别:
1、多线程可以共享全局变量,多进程不能。
2、多线程中,所有子线程的进程号相同;多进程中,不同的子进程进程号不同。
3、线程共享内存空间;进程的内存是独立的。
4、同一个进程的线程之间可以直接交流;两个进程想通信,必须通过一个中间代理来实现。
5、创建新线程很简单;创建新进程需要对其父进程进行一次克隆。
6、一个线程可以控制和操作同一进程里的其他线程;但是进程只能操作子进程。
7、两者最大的不同在于:在多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响;而多线程中,所有变量都由所有线程共享。
三、多线程的优势
进程只有一个,所以分配的CPU资源是一定的,多线程只不过是轮流抢占CPU而已,并不会真正提高处理速度。这意味着,多线程的作用主要在于提高了并发数
Python多线程相当于单核多线程,多线程有两个好处:CPU并行,IO并行,单核多线程相当于自断一臂。所以,在Python中,可以使用多线程,但不要指望能有效利用多核。如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点。不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。
四、进程池的概念:
定义一个池子,在里面放上固定数量的进程,有需求来了,就拿一个池中的进程来处理任务
等到处理完毕,进程并不关闭,而是将进程再放回进程池中继续等待任务
如果有很多任务需要执行,池中的进程数量不够,任务就要等待之前的进程执行任务完毕归来,拿到空闲进程才能继续执行。
也就是说,进池中进程的数量是固定的,那么同一时间最多有固定数量的进程在运行
这样不会增加操作系统的调度难度,还节省了开关进程的时间,也一定程度上能够实现并发效果。
代码:
import time
import multiprocessing
class PrintNumber():
def __init__(self, multi_num):
self.multi_num = multi_num
def run_task(self):
sum_num = 1
for i in range(5):
sum_num = i
time.sleep(1)
print("multi_num = {}, output = {}".format(self.multi_num, sum_num))
return self.multi_num,"ok"
def myCallBack(arg):
print(arg)
if __name__ == "__main__":
#numprocess 要创建的进程数,如果省略,将默认使用cpu_count()的值
#initializer每个工作进程启动时要执行的可调用对象,默认为None
#initargs传给initializer的参数组
process_pool = multiprocessing.Pool()
for i in range(3):
a=1
test = PrintNumber(i)
process_pool.apply_async(test.run_task, args=(),callback=myCallBack)
# close是不允许再向进程池中添加任务
# 必须close+join,否则主进程跑完了,子进程还没完,就会报错
process_pool.close()
process_pool.join()
print("thread join success!")
输出:
multi_num = 0, output = 0
multi_num = 1, output = 0
multi_num = 2, output = 0
multi_num = 0, output = 1
multi_num = 2, output = 1
multi_num = 1, output = 1
multi_num = 0, output = 2
multi_num = 2, output = 2
multi_num = 1, output = 2
multi_num = 0, output = 3
multi_num = 2, output = 3multi_num = 1, output = 3
multi_num = 0, output = 4
(0, 'ok')
multi_num = 1, output = 4
multi_num = 2, output = 4
(2, 'ok')
(1, 'ok')
thread join success!
进程池加锁:
import time
import multiprocessing
def get():
for i in range(3):
time.sleep(1)
print(i)
def task(lock):
lock.acquire() #获取锁
get()
lock.release() #释放锁
def myCallBack(arg):
print(arg)
if __name__ == "__main__":
#numprocess 要创建的进程数,如果省略,将默认使用cpu_count()的值
#initializer每个工作进程启动时要执行的可调用对象,默认为None
#initargs传给initializer的参数组
#进程池的锁需要使用Manager().Lock()
lock=multiprocessing.Manager().Lock()
process_pool = multiprocessing.Pool()
for i in range(3):
process_pool.apply_async(task, args=(lock,))
# close是不允许再向进程池中添加任务
# 必须close+join,否则主进程跑完了,子进程还没完,就会报错
process_pool.close()
process_pool.join()
print("thread join success!")
输出:
0
1
2
0
1
2
0
1
2
thread join success!