zoukankan      html  css  js  c++  java
  • 【廖雪峰老师python教程】——进程与线程

    多进程


    • 操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。
    • 对于操作系统来说,一个任务就是一个进程(Process)
    • 在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。
    • multiprocessing模块就是跨平台版本的多进程模块
      from multiprocessing import Process
      import os
      
      # 子进程要执行的代码
      def run_proc(name):
          print('Run child process %s (%s)...' % (name, os.getpid()))
      
      if __name__=='__main__':
          print('Parent process %s.' % os.getpid())
          p = Process(target=run_proc, args=('test',))
          print('Child process will start.')
          p.start()
          p.join()#等待子进程结束,才继续往下进行
          print('Child process end.')
      Parent process 928.
      Process will start.
      Run child process test (929)...
      Process end.
    • 进程池
      from multiprocessing import Pool
      import os, time, random
      
      def long_time_task(name):
          print('Run task %s (%s)...' % (name, os.getpid()))
          start = time.time()
          time.sleep(random.random() * 3)
          end = time.time()
          print('Task %s runs %0.2f seconds.' % (name, (end - start)))
      
      if __name__=='__main__':
          print('Parent process %s.' % os.getpid())
          p = Pool(4)
          for i in range(5):
              p.apply_async(long_time_task, args=(i,))
          print('Waiting for all subprocesses done...')
          p.close()# 必须先关闭,才能停止添加进程,才能运行
          p.join()
          print('All subprocesses done.')
      Parent process 669.
      Waiting for all subprocesses done...
      Run task 0 (671)...
      Run task 1 (672)...
      Run task 2 (673)...
      Run task 3 (674)...
      Task 2 runs 0.14 seconds.
      Run task 4 (673)...
      Task 1 runs 0.27 seconds.
      Task 3 runs 0.86 seconds.
      Task 0 runs 1.41 seconds.
      Task 4 runs 1.91 seconds.
      All subprocesses done.

    多线程


    • import time, threading
      
      # 新线程执行的代码:
      def loop():
          print('thread %s is running...' % threading.current_thread().name)
          n = 0
          while n < 5:
              n = n + 1
              print('thread %s >>> %s' % (threading.current_thread().name, n))
              time.sleep(1)
          print('thread %s ended.' % threading.current_thread().name)
      
      print('thread %s is running...' % threading.current_thread().name)
      t = threading.Thread(target=loop, name='LoopThread')
      t.start()
      t.join()
      print('thread %s ended.' % threading.current_thread().name)
    • 多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。【锁机制】
      balance = 0
      lock = threading.Lock()
      
      def run_thread(n):
          for i in range(100000):
              # 先要获取锁:
              lock.acquire()
              try:
                  # 放心地改吧:
                  change_it(n)
              finally:
                  # 改完了一定要释放锁:
                  lock.release()
    • 多线程编程,模型复杂,容易发生冲突,必须用锁加以隔离,同时,又要小心死锁的发生。

      Python解释器由于设计时有GIL全局锁,导致了多线程无法利用多核。多线程的并发在Python中就是一个美丽的梦

    ThreadLocal


    • 在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁。

      但是局部变量也有问题,就是在函数调用的时候,传递起来很麻烦:

    一个ThreadLocal变量虽然是全局变量,但每个线程都只能读写自己线程的独立副本,互不干扰。ThreadLocal解决了参数在一个线程中各个函数之间互相传递的问题。

    import threading
    
    # 创建全局ThreadLocal对象:
    local_school = threading.local()
    
    def process_student():
        # 获取当前线程关联的student:
        std = local_school.student
        print('Hello, %s (in %s)' % (std, threading.current_thread().name))
    
    def process_thread(name):
        # 绑定ThreadLocal的student:
        local_school.student = name
        process_student()
    
    t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A')
    t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B')
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    Hello, Alice (in Thread-A)
    Hello, Bob (in Thread-B)

    • 对应到Python语言,单线程的异步编程模型称为协程,有了协程的支持,就可以基于事件驱动编写高效的多任务程序。

    分布式进程


    • 在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上
    • 后期可以学习,现在用不上



  • 相关阅读:
    Educational Codeforces Round 86 (Rated for Div. 2) D. Multiple Testcases
    Educational Codeforces Round 86 (Rated for Div. 2) C. Yet Another Counting Problem
    HDU
    HDU
    HDU
    HDU
    Good Bye 2019 C. Make Good (异或的使用)
    Educational Codeforces Round 78 (Rated for Div. 2) C. Berry Jam
    codeforces 909C. Python Indentation
    codeforces1054 C. Candies Distribution
  • 原文地址:https://www.cnblogs.com/ChaoyuanJam/p/9749718.html
Copyright © 2011-2022 走看看