进程间通信(IPC)
文件
通过读写文件来进行变量, 数据, 信息的传递
读写冲突
两个进程同时进行写, 或者一个写一个读, 造成了冲突.
解决读写冲突
互斥锁
代码语言:javascript复制from multiprocessing import Process, Lock
def save_to_file(index, lock):
with lock:
with open("test.log", "a", encoding="utf-8") as f:
f.write(str(index) "n")
if __name__ == "__main__":
process_array = []
lock = Lock()
for i in range(10):
p = Process(target=save_to_file, args=(i, lock))
process_array.append(p)
p.start()
for p in process_array:
p.join()
print("done!")
套接字(socket-插座)
通过一个协议, 连接两个进程. 主要就是网络请求.
进程A向百度云上传文件, 进程B向百度云下载文件, 不会有冲突.
管道(了解)
用文件的内存缓冲区作为管道, 实现进程间通信
- 匿名管道 主进程和子进程进行交互
- 具名管道 和匿名管道原理是一样的, 不是不相关的进程也可以互相访问
消息队列
就是一个存在内核内存空间中的列表
代码语言:javascript复制redis就是消息队列 socket
from multiprocessing import Queue
def save_to_queue(index, my_queue):
my_queue.put(index)
if __name__ == "__main__":
process_array = []
my_queue = Queue()
for i in range(10):
p = Process(target=save_to_queue, args=(i, my_queue))
process_array.append(p)
p.start()
for p in process_array:
p.join()
while True:
print(my_queue.get())
共享内存(了解)
进程访问内核态同一块内存
代码语言:javascript复制from multiprocessing import Queue, Array, Value
信号量(了解)
不是用来传递数据的, 是用来传递消息
进程B要等到进程A执行到某一步操作后, 才会启动
进程A->发消息->内核->转发信息->进程B
线程间通信
线程间通信强调的是线程之间传递对象引用
共享变量
线程安全
线程有GIL锁, 但是拿到GIL锁不代表可以一直执行下去.
现代计算机多线程也是A执行一会儿, B执行一会儿这样交替执行.
代码语言:javascript复制import requests
import time
from threading import Thread
zero = 0
def foo():
global zero
for i in range(10**7):
zero = 1
zero -= 1
if __name__ == "__main__":
process_array = []
for i in range(2):
p = Thread(target=foo)
process_array.append(p)
p.start()
for p in process_array:
p.join()
print(zero)
解决线程安全
将重要指令包装成原子操作(不可分割的).
- 加互斥锁
import requests
import time
from threading import Thread,Lock
zero = 0
lock = Lock()
def foo():
global zero
for i in range(10**6):
with lock:
zero = 1
zero -= 1
if __name__ == "__main__":
process_array = []
for i in range(2):
p = Thread(target=foo)
process_array.append(p)
p.start()
for p in process_array:
p.join()
print(zero)