美文网首页
线程与多进程

线程与多进程

作者: 牛耀 | 来源:发表于2018-10-15 21:19 被阅读0次

    多任务的线程与进程

    多任务

    • 简单地说,就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。

    进程和程序

    • 编写完毕的代码,在没有运行的时候,称之为程序
      正在运行着的代码,就成为进程
      进程,除了包含代码以外,还有需要运行的环境等,所以和程序是有区别的

    python 操作多进程(fork())

    • 父进程、子进程执行顺序没有规律,完全取决于操作系统的调度算法
    import os
    # fork()函数只能在ubuntu/linux/mac运行
    pid = os.fork()
    if pid == 0:
        print('子进程')
    else:
        print('父进程')
    
    

    getpid()、getppid()

    • 程序执行到os.fork()时,操作系统会创建一个新的进程(子进程),然后复制父进程的所有信息到子进程中。然后父进程和子进程都会从fork()函数中得到一个返回值,在子进程中这个值一定是0,而父进程中是子进程的 id号
    • 子进程永远返回0,而父进程返回子进程的ID。
    • 一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。
    import os
    pid = os.fork()
    if pid == 0:
        print("子进程",os.getpid(),os.getppid())
    else:
        print(pid)
    print("父进程",os.getpid())
    

    多进程修改全局变量

    import os
    import time
    num = 0
    pid = os.fork()
    if pid == 0:
        time.sleep(5)
        print("子进程",num)
        if num == 1:
            print("msg")
    else:
        time.sleep(1)
        num+=1
    print("父进程",num)
    

    多次fork问题(不要使用while True)

    import os.fork
    os.fork()
    os.fork()
    os.fork()
    #fork炸弹
    '''
    while True:
        os.fork()
    '''
    

    多进程中,每个进程中所有数据(包括全局变量)都各有拥有一份,互不影响

    python跨平台多进程模块(multiprocessing)

    from multiprocessing import Process
    import time
    def work(num):
        print(num)
        for i in range(5):
            time.sleep(1)
            print("呵呵")
    p = Process(target = work,args=(1,)) # 创建子进程
    p.start()
    p.join(3)#等子进程结束后 在执行主进程代码 3指的是超时时间
    print("哈哈")
    

    面向对象实现多进程

    from multiprocessing import Process
    import time
    class MyProcess(Process):
        def __init__(self):
            super().__init__() # 初始化父类
        def run(self): # 重写父类方法,方法名必须为run
            for i  in range(5):
                time.sleep(2)
                print('...')
    p = MyProcess()
    p.start()
    p.join() # 表示子进程结束再执行父进程的代码,括号中可以写出等待时间
    print('父进程')
    

    进程池(Pool)

    • apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
    • apply(func[, args[, kwds]]):使用阻塞方式调用func
    • close():关闭Pool,使其不再接受新的任务;
    • terminate():不管任务是否完成,立即终止;
    • join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用
    
    from multiprocessing import Pool
    import time
    def work():
        for i in range(5):
            time.sleep(1)
            print("老王")
    p = Pool(3) # 括号中代表每次执行几个。
    for i in range(3): #指定执行几次work
        p.apply_async(work)#非阻塞
        #p.apply(work)#阻塞
        print("添加成功")
    p.close()#把池子关闭
    p.join()
    

    用Queue实现多进程通信(队列)

    from multiprocessing import Manager,Pool
    import time
    def write(q):
        for i in range(10):
            time.sleep(0.5)
            print("添加成功")
            q.put(i) # 添加
    
    def read(q):
        while True:
            if q.qsize() > 0:
                num =q.get() #取出,取出一个删除一个
                print(num)
                if num == 9:
                    break
    p = Pool(3)
    q = Manager().Queue()
    p.apply_async(write,(q,))
    p.apply_async(read,(q,))
    p.close()
    p.join()
    

    线程(threading)

    • 进程,能够完成多任务,比如 在一台电脑上能够同时运行多个QQ
    • 线程,能够完成多任务,比如 一个QQ中的多个聊天窗口
    import time
    from threading import Thread
    def say():
        time.sleep(1)
        print("我错了,我能站起来了吗?")
    
    for i in range(5):
        #say()
        t = Thread(target=say) #开启一个线程
        t.start()
    
    print("哈哈哈")
    
    • 面向对象线程
    from threading import Thread
    import time
    class MyThread(Thread):
        def run(self):
            for i in range(3):
                time.sleep(1)
                print("我爱你中国")
    t = MyThread()
    t.start() 
    t1 = MyThread()
    t1.start()
    

    多线程修改变量

    多线程全局变量

    from threading import Thread
    import threading 
    import time
    num = 0
    def test1():
        global num #修改全局变量需要提前声明
        num+=1
        time.sleep(1)
        print(threading.currentThread().name)
        print('test1',num)
    def test2():
        time.sleep(3)
        print("test2",num)
    
    t1 = Thread(target=test1)
    t1.start()
    t2 = Thread(target=test2)
    t2.start()
    # 多进程不共享全局变量,多线程共享全局变量
    

    线程修改全局变量

    
    from threading import Thread
    import time
    num = 0
    def test1():
        global num
        for i in range(1000000):
            num+=1
        print(num)
    
    def test2():
        global num
        for i in range(1000000):
            num+=1
        print(num)
    
    t1 = Thread(target=test1)
    t1.start()
    #time.sleep(3)
    t2 =Thread(target=test2)
    t2.start()
    # 不能使用多线程修改全局变量
    

    多线程局部变量

    import threading 
    import time
    def test1():
        num = 0
        if threading.currentThread().name == 'Thread-1':
            num+=1
            time.sleep(1)
            print('threading-1',num)
        else:
            time.sleep(3)
            print(num)
    t1 = Thread(target = test1)
    t1.start()
    t2 = Thread(target = test1)
    t2.start()
    

    加锁

    from threading import Thread
    import time
    num = 0
    flag = True
    def test1():
        global num
        global flag
        if flag:
            for i in range(1000000):
                num+=1
            flag = False
        print(num)
    
    def test2():
        global num
        global flag
        while True:
            if not flag:
                for i in range(1000000):
                    num+=1
                flag = True
                break
        print(num)
    
    t1 = Thread(target=test1)
    t1.start()
    #time.sleep(3)
    t2 =Thread(target=test2)
    t2.start()
    

    互斥锁

    • m.acquire() m.release() 调用一次释放,两个的位置决定是单线程和多线程
    from threading import Thread,Lock
    import time
    num = 0
    def test1():
        global num
        #m.acquire() 单线程
        for i in range(1000000):
            m.acquire() #多线程
            num+=1
            m.release()
        #m.release()
        print(num)
    
    def test2():
        global num
        #m.acquire()
        for i in range(1000000):
            m.acquire()
            num+=1
            m.release()
        #m.release()
        print(num)
    
    m = Lock()
    t1 = Thread(target=test1)
    t1.start()
    #time.sleep(3)
    t2 =Thread(target=test2)
    t2.start()
    

    死锁

    import threading
    import time
    
    class MyThread1(threading.Thread):
        def run(self):
            if mutexA.acquire():
                print(self.name+'----do1---up----')
                time.sleep(1)
    
                if mutexB.acquire():
                    print(self.name+'----do1---down----')
                    mutexB.release()
                mutexA.release()
    
    class MyThread2(threading.Thread):
        def run(self):
            if mutexB.acquire():
                print(self.name+'----do2---up----')
                time.sleep(1)
                if mutexA.acquire():
                    print(self.name+'----do2---down----')
                    mutexA.release()
                mutexB.release()
    
    mutexA = threading.Lock()
    mutexB = threading.Lock()
    
    if __name__ == '__main__':
        t1 = MyThread1()
        t2 = MyThread2()
        t1.start()
    t2.start()
    

    同步

    • 同步就是协同步调,按预定的先后次序多个线程有序执行。
    from threading import Thread,Lock
    from time import sleep
    
    class Task1(Thread):
        def run(self):
            while True:
                if lock1.acquire():
                    print("------Task 1 -----")
                    sleep(0.5)
                    lock2.release()
    
    class Task2(Thread):
        def run(self):
            while True:
                if lock2.acquire():
                    print("------Task 2 -----")
                    sleep(0.5)
                    lock3.release()
    
    class Task3(Thread):
        def run(self):
            while True:
                if lock3.acquire():
                    print("------Task 3 -----")
                    sleep(0.5)
                    lock1.release()
    
    #使用Lock创建出的锁默认没有“锁上”
    lock1 = Lock()
    #创建另外一把锁,并且“锁上”
    lock2 = Lock()
    lock2.acquire()
    #创建另外一把锁,并且“锁上”
    lock3 = Lock()
    lock3.acquire()
    
    t1 = Task1()
    t2 = Task2()
    t3 = Task3()
    
    t1.start()
    t2.start()
    t3.start()
    

    生产者与消费者

    from threading import Thread
    from queue import Queue
    import time
    
    
    def producer():
        global q
        while True:
            if q.qsize() < 1000:
                for i in range(100):
                    q.put("生成"+str(i))
                    print("生成")
            time.sleep(0.5)
    
    
    def consumer():
        global q
        while True:
            if q.qsize() > 600:
                for i in range(3):
                    print("消费"+q.get())
            time.sleep(1)
    
    
    q = Queue()
    for i in range(500):
        q.put("初始化"+str(i))
    
    for i in range(2):
        t1 = Thread(target=producer)
        t1.start()
    
    for i in range(5):
        t = Thread(target=consumer)
    t.start()
    

    异步

    from multiprocessing import Pool
    import time
    
    def test():
        for i in range(5):
            time.sleep(0.5)
            print("做饭中")
        return "饭做好了"
    
    
    def test2(msg):
        print(msg)
    
    p = Pool()
    p.apply_async(func = test,callback = test2)
    
    for i in range(10):
        print("做作业")
    time.sleep(0.5)
    

    相关文章

      网友评论

          本文标题:线程与多进程

          本文链接:https://www.haomeiwen.com/subject/eopqzftx.html