进程/线程池/进程ID/进程间的通讯pipe/Queue/Manager/进程同步

来源:互联网 发布:东吴证券怎么样 知乎 编辑:程序博客网 时间:2024/06/06 12:59
# 1.线程和进程的区别?# 进程 -> 资源的集合# 线程 -> 操作cpu的最小调度单位# 进程和线程谁快? 无法比# 进程至少包含一个线程,进程需要靠线程启动# 线程之间内存是共享的,线程同时修改同一份数据时需要加锁  互斥锁# 递归锁->锁中有锁# 2.join等待线程执行结束 启动线程的语法# def run():# ...# t_joins = []# for i in range(10):# t = threading.Thread(target=run, args("arg", ))# t_joins.append(t)# t.start()# for t in t_joins:# t.join() #等待线程执行结束,线程之间是独立运行的# 3.守护线程:# for i in range(10):# t = threading.Thread(target=run, args("arg", ))# t.setDaemon(True) #设置守护线程# t.start()# 4.队列:# 解耦,使程序松耦合# 提高运行效率# queue.Queue#FIFO# queue.LifoQueue#last come first out# queue.PriorityQueue# 生产者消费者模型->解耦# 5.事件 Event## 6.python的多线程是利用了cpu上下文切换的优势:单线程上下文切换# io操作不占用cpu : 读取数据# 计算占用cpu :#   线程的切换需要来回切换上下文,python的多线程不适合cpu密集型操作的任务,适合io操作密集的任务## 7.多进程:进程之间无GIL概念 数据不可共享 是相互独立的 ->折中的解决# 八核->同一时间同时只能做八个任务(进程)######################################################################################### 1.如何开启一段进程# import multiprocessing# import time,threading## def thread_run():# print(threading.get_ident()) #获取当前线程号## def run(n):# print("start processing %s" % n)# t = threading.Thread(target=thread_run)# t.start()# # time.sleep(1)# if __name__ == "__main__":# for i in range(10):# process = multiprocessing.Process(target=run, args=("进程%s" %i, ))# process.start()# # process.join()######################################################################################## 2.如何获取进程ID# from multiprocessing import Process# import os# def info(title):# print(title)# print("module name:", __name__)# print("parent process,", os.getppid())# print("process id", os.getpid())# print("\n\n")## def f(name):# info('\033[31;1mfunction\033[0m')# print('hello', name)## if __name__ == '__main__':# info('\033[32;1mmain process line\033[0m')# p = Process(target=f, args=('bob',))# p.start()# p.join()######################################################################################## 3.进程间如何通讯# 3.1 Queue形式# from multiprocessing import Process, Queue# import threading, queue## def f(q):# q.put([42, None, 'hello'])## if __name__ == '__main__':# '''进程间的queue 数据共享'''# q = Queue()# p = Process(target=f, args=(q,))# '''线程间的数据共享'''# # q = queue.Queue()# # p = threading.Thread(target=f, args=(q,))# '''进程间数据不能用线程间共享'''# # q = queue.Queue()# # p = Process(target=f, args=(q,))# p.start()# print(q.get())  # prints "[42, None, 'hello']"# p.join()# # 进程间的数据共享和线程间的数据共享不是一回事 线程间的数据共享是同一份数据 进程间的数据共享其实是通过pikle序列化和反序列化克隆后的结果# 3.2管道形式 pipe# from multiprocessing import Process, Pipe## def f(conn):# conn.send([42, None, 'hello from child'])# conn.send([42, None, 'hello from child'])# conn.close()## if __name__ == '__main__':# parent_conn, child_conn = Pipe() #管道两遍分别交给两边# p = Process(target=f, args=(child_conn,))# p.start()# print(parent_conn.recv())  # prints "[42, None, 'hello']"# print(parent_conn.recv())# p.join()# 3.3Manager完全同步(真正的共享,且不需要加锁,manager中已经加锁)# from multiprocessing import Process, Manager# import os## def f(d, l):# # d[1] = '1'# # d['2'] = 2# # d[0.25] = None# # l.append(1)# d[os.getpid()] = os.getpid()# l.append(os.getpid())# print(l)## if __name__ == '__main__':# with Manager() as manager:  #赋值变量# d = manager.dict()  #生成一个字典,可在多个进程间共享和传递## l = manager.list(range(5))  #生成列表,可在多个进程间共享和传递# p_list = []# for i in range(10):# p = Process(target=f, args=(d, l))# p.start()# p_list.append(p)# for res in p_list:  #等待结果# res.join()## print(d)# print(l)# 3.4 进城同步  因为屏幕共享 控制屏幕打印不会乱# 起一个进程相当于克隆一份父进程的数据 开销很大# from multiprocessing import Process, Lock## def f(l, i):# l.acquire()# try:# print('hello world', i)# finally:# l.release()## if __name__ == '__main__':# lock = Lock()## for num in range(10):# Process(target=f, args=(lock, num)).start()######################################################################################## 4.进程池 避免进程太多 开销太大# apply:串行# apply_async:并行# from multiprocessing import Process, Pool# import time,os# # def Foo(i):# time.sleep(2)# print("in process ",os.getpid())# return i + 100# # def Bar(arg):# print("子进程中pid:", os.getpid())# print('-->exec done:', arg) #回调函数是父进程调用的 可以避免子进程的多次连接数据库等等 提高效率# if __name__ == "__main__":   #为了区分你是主动执行这个脚本还是通过模块去调用 手动执行脚本 __name__为main 用模块调用则是模块名  测试用# pool = Pool(processes=5)  #允许进程池同时放入五个进程 多余的将会排队不会被执行# print("主进程中pid:",os.getpid())# for i in range(10):# pool.apply_async(func=Foo, args=(i,), callback=Bar)  #callback回调执行完后执行# # pool.apply(func=Foo, args=(i,))  #往进程池里放一个进程# # pool.close()# pool.join()  # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。# print('end')

原创粉丝点击