zoukankan      html  css  js  c++  java
  • 人生苦短之我用Python篇(线程/进程、threading模块:全局解释器锁gil/信号量/Event、)


    线程: 有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。是一串指令的集合。
    线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。
    在单个程序中同时运行多个线程完成不同的工作,称为多线程

    进程: qq 要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用等。。。
    对各种资源管理的集合 就可以成为进程。

    进程 要操作cpu , 必须要先创建一个线程,
    all the threads in a process have the same view of the memory
    所有在同一个进程里的线程是共享同一块内存空间的


    进程与线程的区别?

    Threads share the address space of the process that created it; processes have their own address space.
    线程共享内存空间,进程的内存是独立的
    Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.

    Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
    同一个进程的线程之间可以直接交流,两个进程想通信,必须通过一个中间代理来实现

    New threads are easily created; new processes require duplication of the parent process.
    创建新线程很简单, 创建新进程需要对其父进程进行一次克隆

    Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
    一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程

    Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.


    threading模块

    import time
    import threading
    
    def run(n):
        print('task.....',n)
        time.sleep(2)
    
    # run("t1")
    # run("t2")
    

    #普通写法
    t1 = threading.Thread(target=run,args=("t1",)) t2 = threading.Thread(target=run,args=("t2",)) t1.start() t2.start()



    import time
    import threading
    #类写法
    class MyThread(threading.Thread):
        def __init__(self,n,sleep_time):
            super(MyThread, self).__init__()
            self.n = n
            self.sleep_time = sleep_time
        def run(self):
            print("task", self.n)
            time.sleep(self.sleep_time)
            print("task done")
    
    t1 = MyThread("t1",2)
    t2 = MyThread("t2",4)
    
    t1.start()
    t2.start()
    import threading
    import time
    
    def run(n):
        print("task ",n )
        time.sleep(2)
        print("task done",n)
    
    start_time = time.time()
    t_objs = [] #存线程实例
    for i in range(50):
        t = threading.Thread(target=run,args=("t-%s" %i ,))
        t.start()
        t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里
    
    for t in t_objs: #循环线程实例列表,等待所有线程执行完毕
        t.join()
    
    print(t_objs)
    print("----------all threads has finished...")
    print("cost:",time.time() - start_time)
    Daemon:守护进程,即主进程一结束,守护进程也就结束
    import threading
    import time
    
    def run(n):
        print("task ",n )
        time.sleep(2)
        print("task done",n,threading.current_thread())
    
    start_time = time.time()
    t_objs = [] #存线程实例
    for i in range(50):
        t = threading.Thread(target=run,args=("t-%s" %i ,))
        t.setDaemon(True) #把当前线程设置为守护线程
        t.start()
        t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里
    
    # for t in t_objs: #循环线程实例列表,等待所有线程执行完毕
    #     t.join()
    
    # time.sleep(2)
    print("----------all threads has finished...",threading.current_thread(),threading.active_count())
    print("cost:",time.time() - start_time)

    全局锁

    import threading
    import time
    
    def run(n):
        lock.acquire()#获得锁,除非释放掉锁,否则其他线程就不能再次获得,2.7中试,3.0以后不需要了
        global  num
        num +=1
        # time.sleep(1)
        lock.release()#释放锁,其他线程可以获得了
    
    
    lock = threading.Lock()
    num = 0
    t_objs = [] #存线程实例
    for i in range(50):
        t = threading.Thread(target=run,args=("t-%s" %i ,))
        t.start()
        t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里
    
    for t in t_objs: #循环线程实例列表,等待所有线程执行完毕
        t.join()
    
    print("----------all threads has finished...",threading.current_thread(),threading.active_count())
    print("num:",num)


     信号量:即同时可以获得多个锁

    import threading
    import time
    
    def run(n):
        semaphore.acquire()#信号量获取
        time.sleep(1)
        print("run the thread :%s
    " %n)
        semaphore.release()#信号量释放
    
    
    if __name__ == "__main__":
        semaphore = threading.BoundedSemaphore(5)   #设置信号量,即绑定信号量可以同时拥有的锁的数量
        for i in range(22):
            t = threading.Thread(target = run,args = (i,))
            t.start()
    
    while threading.active_count() !=1 :#当前活跃的线程数
        pass
    
    else:
        print("______-all threads done______")

    Event:

    event = threading.Event()#生成event对象
    event.set()#设置event标志位
    event.clear()#清除event标志位
    event.is_set():#判断event是否设置了标志位

     红绿灯例子:

    import time
    import threading
    
    event = threading.Event()#生成event对象
    def lighter():
        event.set()#设置event标志位
        count = 0
        while True:
            if count >5 and count <10:
                event.clear()#清除event标志位
                print("33[41;1m红灯亮....33[0m")
            elif count > 10:
                event.set()
                print("33[42;1m绿灯亮了....33[0m")
                count = 0
            else:
                print("33[42;1m绿灯亮着33[0m")
            time.sleep(1)
            count +=1
    
    def car(n):
        while True:
            if event.is_set():#判断event是否设置了标志位
                print('33[34;2m[%s] running..... 33[0m'%n)
                time.sleep(0.5)
            else:
                print('[%s] stoping.....'%n)
                event.wait()
                print('路灯亮了[%s]开跑'%n)
    
    
    light = threading.Thread(target=lighter,)
    light.start()
    
    car1 = threading.Thread(target=car,args=('宝马',))
    car1.start()
    
    car2 = threading.Thread(target=car,args=('大奔驰',))
    car2.start()
    
    car3 = threading.Thread(target=car,args=('玛莎拉蒂',))
    car3.start()


    多进程:

    和线程用法基本一致,我threading.Thread换成multiprocessing.Process

    import time,threading
    import multiprocessing
    
    def thread_run():
        print(threading.get_ident())
    
    def run(name):
        time.sleep(2)
        print("hellp",name)
        t = threading.Thread(target=thread_run,)
        t.start()
    
    if __name__ =="__main__":
        for i in range (10):
            p = multiprocessing.Process(target=run,args=("bob %s"%i,))#与线程用法基本机制
            p.start()

     数据在不同进程间进行交换

    from multiprocessing import Process,Queue
    
    def f(qq):
        qq.put([42,None,156161])
    
    if __name__ =="__main__":
        q =Queue()#可以在不同进程间交互使用
        p = Process(target=f,args=(q,))#把q作为参数传入
        p.start()
        print(q.get())#父进程可以得到子进程中修改过的数据
        p.join()

     进程池

    Note:  from multiprocessing import Process, Pool,freeze_support

      pool = Pool(processes=5) #允许进程池同时放入5个进程
      pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback=回调,父进程操作
      #pool.apply(func=Foo, args=(i,)) #串行
      #pool.apply_async(func=Foo, args=(i,)) #并行
    from  multiprocessing import Process, Pool,freeze_support
    import time
    import os
    
    def Foo(i):
        time.sleep(2)
        print("in process",os.getpid())
        return i + 100
    
    def Bar(arg):
        print('-->exec done:', arg,os.getpid())
    
    if __name__ == '__main__':#window必须加这一句
        #freeze_support()
        pool = Pool(processes=5) #允许进程池同时放入5个进程
        print("主进程",os.getpid())
        for i in range(10):
            pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback=回调
            #pool.apply(func=Foo, args=(i,)) #串行
            #pool.apply_async(func=Foo, args=(i,)) #并行
        print('end')
        pool.close()
        pool.join() #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。.join()

     进程锁:变串行了

    from multiprocessing import Process, Lock
    
    
    def f(l, i):
        #l.acquire()
        print('hello world', i)
        #l.release()
    
    
    if __name__ == '__main__':
        lock = Lock()
    
        for num in range(100):
            Process(target=f, args=(lock, num)).start()

     Manager:进程间交换数据

    from multiprocessing import Process, Manager
    import os
    def f(d, l):
        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)

     Pipe:生成两个可以交互数据的进程

    parent_conn, child_conn = Pipe()#生成两个可以交换数据的进程
    from multiprocessing import Process, Pipe
    
    
    def f(conn):
        conn.send([42, None, 'hello from child'])
        conn.send([42, None, 'hello from child2'])
        print("from parent:",conn.recv())
        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())  # prints "[42, None, 'hello']"
        parent_conn.send("可好") # prints "[42, None, 'hello']"
        p.join()
    
    








  • 相关阅读:
    POJ 3037 Skiing(Dijkstra)
    HDU 1875 畅通工程再续(kruskal)
    HDU 1233 还是畅通工程(Kruskal)
    Java实现 LeetCode 754 到达终点数字(暴力+反向)
    Java实现 LeetCode 754 到达终点数字(暴力+反向)
    Java实现 LeetCode 754 到达终点数字(暴力+反向)
    Java实现 LeetCode 753 破解保险箱(递归)
    Java实现 LeetCode 753 破解保险箱(递归)
    Java实现 LeetCode 753 破解保险箱(递归)
    Java实现 LeetCode 752 打开转盘锁(暴力)
  • 原文地址:https://www.cnblogs.com/tcheng/p/5908621.html
Copyright © 2011-2022 走看看