进程间通信(IPC)

  • 文件

    通过读写文件来进行变量, 数据, 信息的传递

    • 读写冲突

      两个进程同时进行写, 或者一个写一个读, 造成了冲突.

    • 解决读写冲突

      • 互斥锁

        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向百度云下载文件, 不会有冲突.

    socket.png

  • 管道(了解)

    用文件的内存缓冲区作为管道, 实现进程间通信

    • 匿名管道

      主进程和子进程进行交互

    • 具名管道

      和匿名管道原理是一样的, 不是不相关的进程也可以互相访问

    ipc_pipeline.png

  • 消息队列

    就是一个存在内核内存空间中的列表

    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())
  • 共享内存(了解)

    进程访问内核态同一块内存

    from multiprocessing import Queue, Array, Value
  • 信号量(了解)

    不是用来传递数据的, 是用来传递消息

    进程B要等到进程A执行到某一步操作后, 才会启动

    进程A->发消息->内核->转发信息->进程B

线程间通信

线程间通信强调的是线程之间传递对象引用

  • 共享变量

    • 线程安全

      线程有GIL锁, 但是拿到GIL锁不代表可以一直执行下去.

      现代计算机多线程也是A执行一会儿, B执行一会儿这样交替执行.

      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)
Last modification:September 5, 2022
如果觉得我的文章对你有用,请随意赞赏