美文网首页
Python-进程VS线程

Python-进程VS线程

作者: 时光清浅_许你心安_ | 来源:发表于2018-08-24 22:12 被阅读0次

    进程和线程

    进程之间的通信: q = multiprocessing.Queue()
    进程池之间的通信: q = multiprocessing.Manager().Queue()
    线程之间的通信: q = queue.Queue()

    功能

    • 进程,能够完成多任务,比如 在一台电脑上能够同时运行多个QQ
    • 线程,能够完成多任务,比如 一个QQ中的多个聊天窗口

    定义的不同

    进程是系统进行资源分配和调度的一个独立单位.
    线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源

    区别

    • 一个程序至少有一个进程,一个进程至少有一个线程.
    • 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高。
    • 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率
    • 线程不能够独立执行,必须依存在进程中

    优缺点

    • 线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反

    互斥锁

    • 当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
      线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。

    • 互斥锁为资源引入一个状态:锁定/非锁定。

    • 某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

      threading模块中定义了Lock类,可以方便的处理锁定:

    #创建锁
    mutex = threading.Lock()
    #锁定
    mutex.acquire([blocking])
    #释放
    mutex.release()
    

    多线程-非共享数据

    对于多线程中全局变量和局部变量是否共享

    • 多线程局部变量
    #coding=utf-8
        import threading
        import time
    
        class MyThread(threading.Thread):
            # 重写 构造方法
            def __init__(self,num,sleepTime):
                threading.Thread.__init__(self)
                self.num = num
                self.sleepTime = sleepTime
    
            def run(self):
                self.num += 1
                time.sleep(self.sleepTime)
                print('线程(%s),num=%d'%(self.name, self.num))
    
        if __name__ == '__main__':
            mutex = threading.Lock()
            t1 = MyThread(100,5)
            t1.start()
            t2 = MyThread(200,1)
            t2.start()
    

    运行结果:

    线程(Thread-2),num=201
    线程(Thread-1),num=101
    

    多线程全局变量

    import threading
    from time import sleep
    def test(sleepTime):
        num = 1
        sleep(sleepTime)
        num+=1
        print('---(%s)--num=%d'%(threading.current_thread(), num))
    if __name__ == '__main__':
        t1 = threading.Thread(target = test,args=(5,))
        t2 = threading.Thread(target = test,args=(1,))
    
        t1.start()
        t2.start()
    

    运行结果:

    ---(<Thread(Thread-2, started 10876)>)--num=2
    ---(<Thread(Thread-1, started 7484)>)--num=2
    
    • 在多线程开发中,全局变量是多个线程都共享的数据,而局部变量等是各自线程的,是非共享的

    同步应用

    • 多个线程有序执行
    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()
    

    运行结果:

    ------Task 1 -----
    ------Task 2 -----
    ------Task 3 -----
    ------Task 1 -----
    ------Task 2 -----
    ------Task 3 -----
    ------Task 1 -----
    ------Task 2 -----
    ------Task 3 -----
    ------Task 1 -----
    ------Task 2 -----
    ------Task 3 -----
    ------Task 1 -----
    ------Task 2 -----
    ------Task 3 -----
    ------Task 1 -----
    ------Task 2 -----
    ------Task 3 -----
    ------Task 1 -----
    ------Task 2 -----
    ------Task 3 -----
    ...........`
    
    • 可以使用互斥锁完成多个任务,有序的进程工作,这就是线程的同步

    生产者与消费者模式

    Python的Queue模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue。这些队列都实现了锁原语(可以理解为原子操作,即要么不做,要么就做完),能够在多线程中直接使用。可以使用队列来实现线程间的同步。

    • 用FIFO队列实现上述生产者与消费者问题的代码如下:
    import threading,time
    from queue import Queue
    class Producer(threading.Thread):
        def run(self):
            global queue
            count = 0
            while True:
                if queue.qsize() < 1000:
                    for i in range(100):
                        count = count +1
                        msg = '生成产品'+str(count)
                        queue.put(msg)
                        print(msg)
                time.sleep(0.5)
    class Consumer(threading.Thread):
        def run(self):
            global queue
            while True:
                if queue.qsize() > 100:
                    for i in range(3):
                        msg = self.name + '消费了 '+queue.get()
                        print(msg)
                time.sleep(1)
    if __name__ == '__main__':
        queue = Queue()
        for i in range(500):
            queue.put('初始产品'+str(i))
        for i in range(2):
            p = Producer()
            p.start()
        for i in range(5):
            c = Consumer()
            c.start()
    

    运行结果:

    生成产品1
    生成产品2
    生成产品1
    生成产品3
    生成产品2
    生成产品4
    Thread-3消费了 初始产品0
    生成产品3
    生成产品5
    Thread-3消费了 初始产品1
    生成产品4
    生成产品6
    Thread-4消费了 初始产品2
    Thread-3消费了 初始产品3
    生成产品5
    生成产品7
    Thread-4消费了 初始产品4
    生成产品6
    生成产品8
    Thread-5消费了 初始产品5
    Thread-4消费了 初始产品6
    ...........
    
    • 此时就出现生产者与消费者的问题

    Queue的说明

    1.对于Queue,在多线程通信之间扮演重要的角色
    2.添加数据到队列中,使用put()方法
    3.从队列中取数据,使用get()方法
    4.判断队列中是否还有数据,使用qsize()方法

    相关文章

      网友评论

          本文标题:Python-进程VS线程

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