• Python之多进程、多线程---王要胜---2020-01-01


    Python之多进程、多线程
    一、什么是进程?
    区分两个概念程序和进程
    程序:计算机程序只不过是磁盘中可执行的二进制等数据。它们只用在被读取到内存中,被操作系统调用时才开始自己的生命周期。
    进程(有时被称为重量级进程)是程序的一次执行。每个进程都有自己的地址空间、内存、数据栈以及其它其运行相关的数据。操作系统管理在其上运行的所有进程。进程间都有自己的内存空间、数据栈等,所以只能使用进程间通讯,而不能直接共享信息。
    程序与进程的主要区别
    1)程序是永存的;进程是暂时的,是程序在数据集上的一次执行,有创建有撤销,存在是暂时的;
    2)程序是静态的观念,进程是动态的观念;
    进程具有并发性,而程序没有;
    进程是竞争计算机资源的基本单位,程序不是。
    进程和程序不是一一对应的: 一个程序可对应多个进程即多个进程可执行同一程序; 一个进程可以执行一个或几个程序

    二、什么是线程?
    线程(有时被称为轻量级进程)跟进程有些相似,不同的是,线程运行在进程中,同一个进程中的线程共享相同的运行环境。
    线程与进程的关系
    线程有开始,顺序执行和结束三部分。它有一个自己的指令指针,记录自己运行到的地方。线程的运行可以被抢占(中断),或者被暂时挂起(睡眠),让其他线程执行。一个进程中的各个线程之间共享同一片数据空间,所以线程之间可以比进程之间更方便地共享数据和相互通讯。
    在多线程并发运行时,如果多个线程共同访问同一片数据,则可能由于数据访问的顺序不一致,有可能导致数据结果不一致。所以线程共享内存是有一定危险性的。

    三、什么是Python中的全局解释器锁(GIL)?
    Python代码的执行时由Python虚拟机来控制的,其实Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行。虽然Python解释器中可以运行多个线程,但是在任意时刻,只有一个线程在解释器中运行。
    对于Python虚拟机的访问由全局解释器锁(Global interpreter lock)来控制,正是由于这个锁能使同一时刻只有一个线程在运行。
    四、在Python中使用多进程
    注意:每当使用multiprocessing创建新的进程,会复制主进程的所有状态和参数。所以此时调用主进程的全局变量是可以的,但是修改之后不会上传会主进程。
    在系统中除了初始化进程,每一个进程都有一个父进程,可能有0个或者多个子进程。由此形成父子进程关系。

    在Python中提供了几个用于多进程的模块,今天主要通过Python的multiprocessing模块来创建多进程。

    Python多进程示例一:

    ! -- coding:utf8 --

    import multiprocessing
    from time import sleep, ctime

    def work(flag=0):
    print("work %s start!" % flag, ctime())
    sleep(4)
    print("work %s end!" % flag, ctime())

    if name == 'main':
    t1 = multiprocessing.Process(target=work, args=(1,))
    t2 = multiprocessing.Process(target=work, args=(2,))
    t3 = multiprocessing.Process(target=work, args=(3,))
    t1.start()
    t2.start()
    t3.start()

    Python多进程示例二:

    ! -- coding:utf8 --

    import multiprocessing
    from time import sleep, ctime

    def work(flag=0):
    print("work %s start!" % flag, ctime())
    sleep(4)
    print("work %s end!" % flag, ctime())

    process_num = 5

    def main():
    process = []
    for i in range(process_num):
    t = multiprocessing.Process(target=work, args=(i,))
    process.append(t)

    for i in process:
        i.start()
    
    for i in process:
        i.join()
    

    if name == 'main':
    main()

    Python多进程示例三:

    ! -- coding:utf8 --

    import multiprocessing
    from time import sleep, ctime
    import os

    class MyProcess(multiprocessing.Process):

    def __init__(self, flag):
        multiprocessing.Process.__init__(self)
        self.flag = flag
    
    def run(self):
        print("work %s start!" % self.flag, ctime())
        print("子进程%s开始执行,pid=%s; 父进程:ppid=%s" % (self.flag, os.getpid(), os.getppid()))
        sleep(4)
        print("work %s end!" % self.flag, ctime())
    

    process_num = 5

    def main():
    process = []
    for i in range(process_num):
    t = MyProcess(i)
    process.append(t)

    for i in process:
        i.start()
    
    for i in process:
        i.join()
    

    if name == 'main':
    main()

    Python多进程之进程池:
    为什么要用进程池?
    原因 :如果有大量任务需要多进程完成,则可能需要频繁的创建删除进程,给进算计带来较多的资源消耗。
    原理 :创建适当的进程放入进程池,用来处理待处理事件,处理完毕后进程不销毁,仍然在进程池中等待处理其他事件。 进程的复用降低了资源的消耗。

    Python多进程示例四:

    ! -- coding:utf8 --

    import multiprocessing
    from time import sleep, ctime
    import os

    def work(flag=0):
    print("work %s start!" % flag, ctime())
    sleep(4)
    print("work %s end!" % flag, ctime())
    return "work %s success" % flag

    def main():
    #创建线程池
    pool_num = multiprocessing.Pool(4)

    process = []
    
    for i in range(10):
        p = pool_num.apply_async(func=work, args=(i,))
        process.append(p)
    
    #关闭线程池
    pool_num.close()
    #回收
    pool_num.join()
    
    for i in process:
        print(i.get())
    

    if name == 'main':
    main()

    五、在Python中使用多线程
    注意:
    在Python多线程下,每个线程的执行方式:
    获取GIL(Global Interpreter Lock(全局解释器锁))
    执行代码直到sleep或者是Python虚拟机将其挂起
    释放GIL
    在Python中提供了几个用于多线程的模块,包括thread、threading等,thread和threading允许程序员创建和管理线程。

    Python多线程示例一:

    ! -- coding:utf8 --

    import threading
    from time import sleep, ctime

    def work(flag=0):
    print("work %s start!" % flag, ctime())
    sleep(4)
    print("work %s end!" % flag, ctime())

    if name == 'main':
    t1 = threading.Thread(target=work, args=(1,))
    t2 = threading.Thread(target=work, args=(2,))
    t3 = threading.Thread(target=work, args=(3,))
    t1.start()
    t2.start()
    t3.start()

    Python多线程示例二:

    ! -- coding:utf8 --

    import threading
    from time import sleep, ctime

    def work(flag=0):
    print("work %s start!" % flag, ctime())
    sleep(4)
    print("work %s end!" % flag, ctime())

    thread_num = 5

    def main():
    threads = []
    for i in range(thread_num):
    t = threading.Thread(target=work, args=(i,))
    threads.append(t)

    for i in threads:
        i.start()
    
    for i in threads:
        i.join()
    

    if name == 'main':
    main()

    Python多线程示例三:

    ! -- coding:utf8 --

    import threading
    from time import sleep, ctime

    class MyThread(threading.Thread):

    def __init__(self, flag):
        threading.Thread.__init__(self)
        self.flag = flag
    
    def run(self):
        print("work %s start!" % self.flag, ctime())
        sleep(4)
        print("work %s end!" % self.flag, ctime())
    

    thread_num = 5

    def main():
    threads = []
    for i in range(thread_num):
    t = MyThread(i)
    threads.append(t)

    for i in threads:
        i.start()
    
    for i in threads:
        i.join()
    

    if name == 'main':
    main()

    Python多线程之线程同步
    如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。
    多线程的优势在于可以同时运行多个任务。但是当线程需要共享数据时,可能存在数据不同步的问题。

    Python多线程示例四:

    ! -- coding:utf8 --

    import threading
    from time import sleep, ctime

    sum = 0

    class MyThread(threading.Thread):

    def __init__(self, flag, my_lock):
        threading.Thread.__init__(self)
        self.flag = flag
        self.my_lock = my_lock
    
    
    def run(self):
        print("work %s start!" % self.flag, ctime())
        self.my_lock.acquire()
        global sum
        for i in range(100000):
            sum = sum + 1
        self.my_lock.release()
        print("work %s end!" % self.flag, ctime())
    

    thread_num = 5

    def main():
    thread_lock = threading.Lock()
    threads = []
    for i in range(thread_num):
    t = MyThread(i, thread_lock)
    threads.append(t)

    for i in threads:
        i.start()
    
    for i in threads:
        i.join()
    

    if name == 'main':
    main()
    print(sum)

  • 相关阅读:
    最基础的账户余额要怎么在 mysql 实现?
    跳跃表时间复杂度分析推导
    Redis:RDB 中 fork 的使用
    字段、约束和索引在存储过程中的判断
    高效沟通的基本流程
    人月神话--画蛇添足
    课程评价及加分项
    人月神话--提纲挈领
    热词搜索七
    《大道至简:软件工程实践者的思想》
  • 原文地址:https://www.cnblogs.com/niaocaizhou/p/12130238.html
Copyright © 2020-2023  润新知