线程:简单来说,一个进程中包含多个线程,比如打开一个 QQ(进程),然后你一边聊 QQ(一个线程),一边用 QQ 传送文件(一个线程),等等。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程( Thread )。
进程是CPU资源分配的基本单位,
线程是独立运行和独立调度的基本单位(CPU上真正运行的是线程)。
进程拥有自己的资源空间,一个进程包含若干个线程,线程与CPU资源分配无关,多个线程共享同一进程内的资源。
在大多数编程语言中因为切换消耗的资源更少,多线程比多进程效率更高
对于python:
对CPU密集型代码(比如循环计算,海量运算,机器学习等) : 多进程效率更高
对IO密集型代码(比如文件操作,网络爬虫): 多线程效率更高。
进程multiprocessing
import multiprocessing
import os
from multiprocessing import cpu_count
from multiprocessing import Pool
import time
if __name__ == '__main__':N = int(input())# 多进程CPU_COUNT =cpu_count() ##CPU内核数 本机为8pool = Pool(CPU_COUNT)#进程池创建result = []for i in range(CPU_COUNT):result.append(pool.apply_async(howMany, (sepList[i], )))#创建进程
#Pool对象调用join方法,会等待所有的子进程执行完毕;
#调用join方法之前,必须调用close;
#调用close之后,就不能继续添加新的Process了。pool.close()#pool.join()ans = 0list = [res.get() for res in result]print(sum(list), end = '')
锁案例
import multiprocessing
def func(lock, data):lock.acquire()try:# 在这里对共享数据进行操作data.value += 1finally:lock.release()if __name__ == '__main__':lock = multiprocessing.Lock()data = multiprocessing.Value('i', 0)p1 = multiprocessing.Process(target=func, args=(lock, data))p2 = multiprocessing.Process(target=func, args=(lock, data))p1.start()p2.start()p1.join()p2.join()print(data.value)
锁:l.acquire()
释放 l.release()
pool.close() 关闭进程池,无法通过该进程池再创建新进程
pool.join() 主进程阻塞等待子进程的退出
线程:threading
if __name__ == '__main__':N = int(input())threadNum = 32t = []sepList = seprateNum(N, threadNum)for i in range(0, threadNum):t.append(threading.Thread(target = howMany, args = (sepList[i], )))t[i].start()for i in range(0, threadNum):t[i].join()print(N - 1 - ans, end = '')
lock = threading.Lock()
lock.acquire()#互斥锁 保证一个线程在运行时不会读到这个global_num += 1lock.release()
为了更好解决这个问题,Python 线程库实现了 ThreadLocal 变量(很多语言都有类似的实现,比如 Java)。ThreadLocal 真正做到了线程之间的数据隔离,并且使用时,不需要手动获取自己的线程 ID,如下示例:
import threading
global_data = threading.local()def show():print (threading.current_thread().getName(), global_data.num)
def thread_cal():global_data.num = str(threading.current_thread().getName()).split("-")[1]show()thread = []
for i in range(10):thread.append(threading.Thread(target = thread_cal))thread[i].start()
for i in range(10):thread[i].join()print ("Main thread: ", global_data.__dict__ )
输出为每个线程名称
上面示例中,每个线程都可以通过 global_data.num, 获得自己独有的数据,并且每个线程读取到的 global_data 都不同,真正做到线程之间的隔离。c0ab1072ab50e3eaaa6a0f3726c6bb7e.png