day 29

day 29 进程互斥锁、队列、进程间通信、线程

01.进程互斥锁

  1. 可以让并发变成串行,牺牲了执行效率保证了数据安全

  2. from multiprocessing import Lock
    mutex = Lock() # 创建一个锁对象
    mutes.acquire() # 加锁
    '''需要进程串行的功能,多为对数据的修改操作'''
    mutes.release() # 释放锁
    
  3. 在程序并发执行时,需要修改数据时使用

02.队列

  1. 相当于内存中的一个空间,可以存放多个数据,队列数据顺序为先到先排到前面,先进先出

  2. 堆栈;最先进来的最后出去

  3. from multiprocessing import Queue
    q=Queue(5) # 表示队列中可以存放5个数据
    q=Queue() # 不传参表示可以存放无限多的数据,硬件支持下的最大值
    
  4. q.put(数据) # 添加数据,若队列中的数据满了则等待空位出现
    q.empty() # 判断队列是否为空
    q.get() # 从队列中获取数据,若对列中为空,则等待数据
    q.get_mowait() # 同样是获取数据,若没有则报错
    q.full() # 判断队列是否满了
    q.put_mowait() # 同样是添加数据,队列如果满了则报错
    
  5. pass

03.IPC 进程间通信

  1. 进程间数据是隔离的,可以通过队列进行通信

  2. from multiprocessing import Process
    from multiprocessing import Queue
    
    def test1(q):
      	data='数据'
        q.put(data)
        print('进程1向队列中添加数据')
        
    def test2(q):
      	data=q.get()
        print(data)
    
    if __name__ == '__main__':
      	q=Queue() # 创建一个队列
        p1=Process(target=test1,args=(q,))
        p2=Process(target=test2,args=(q,))
        p1.start()
        p2.start()
        p2.join()
        print('主')
        
    

04.生产者与消费者

  1. 生产者;生产数据的

  2. 消费者;使用数据的

  3. 在程序中,生产者将数据放入队列中,消费者从队列中获取数据

  4. from multiprocessing import Process
    from multiprocessing import Queue
    import time
    
    
    def producer(name, food, q):
        for i in range(9):
            data = food, i + 1
            print(f'用户{name}制作{data}')
            q.put(data)
            time.sleep(0.5)
    
    
    def consumer(name, q):
        while True:
            data = q.get()
            if not data:
                break
            print(f'用户{name}食用{data}')
    
    
    if __name__ == '__main__':
        q = Queue()
    		p1 = Process(target=producer, args=('logan', '牛肉干', q))
    		c1 = Process(target=consumer, args=('tank', q))
    		c2 = Process(target=consumer, args=('nick', q))
    		p1.start()
        c1.daemon = True
        c2.daemon = True
    		c1.start()
    		c2.start()
    		p1.join()
    		print('主')
    

05.线程

  1. 线程与进程都是虚拟单位,为了更好的描述某种事物

  2. 进程;资源单位

  3. 线程;执行单位

  4. 线程之间数据是共享的

  5. 开启一个进程一定会有一个线程,线程才是真正的执行者

  6. 为什么要使用线程;节省内存资源

    1. 开启进程;
      1. 开辟一个名称空间;没开启一个进程都会占用一份内存资源
      2. 会自带一个线程
    2. 开启线程
      1. 一个进程可以开启多个线程
      2. 线程的开销远小于进程
    3. 线程不能实现并行,只能实现并发
  7. # 创建线程的方法一
    from threading import Thread
    import time
    
    
    def test1(name):
        print(f'线程{name}开启')
        time.sleep(1)
        print(f'线程{name}结束')
    
    
    if __name__ == '__main__':
        t1 = Thread(target=test1, args=(1,))
        t2 = Thread(target=test1, args=(2,))
        t1.daemon = True
        t2.daemon = True
        t1.start()
        t2.start()
        time.sleep(3)
        print('主')
        
    # 方法二 自定义类
    from threading import Thread
    import time
    
    class MyThread(Thread):
        def run(self):
            print('线程开始')
            time.sleep(1)
            print('线程结束')
    if __name__ == '__main__':
        t=MyThread()
        t.start()
        t.join()
        print('主')
    
    
  8. 线程对象的属性

  9. t.isAlive() # 判断该进程是否存活
    t.is_alive() # 判断该进程是否存活
    t.getName() # 获取当前线程号
    current_thread().name # 获取当前线程号
    t.daemon = True # 守护线程,只要主线程结束,该子线程也跟着结束
    t.isDaemon() # 判断该进程是否为守护进程
    
  10. 线程互斥锁 # 与进程互斥锁完全相同

  11. from threading import Thread
    from threading import Lock
    import time
    
    mutex = Lock() # 创建一个锁对象
    n=100 # 子线程是可以修改主线程的数据的
    def tast(i):
        print(f'线程{i}启动')
        global n # 使函数内的n变为全剧变量
        # mutex.acquire() # 上锁
        nj=n
        time.sleep(0.1) # 模拟网络延迟,让进程等待0.1秒,使下一个进程获取到的n为未修改前的n
        n=nj-1
        print(n)
        # mutex.release() # 开锁
    
    if __name__ == '__main__':
        t_lis=[]
        for i in range(30):
            t=Thread(target=tast,args=(i,))
            t_lis.append(t)
            t.start()
            # t.join()
    
        for i in t_lis:
            i.join()
    
        print('主')
    
原文地址:https://www.cnblogs.com/luocongyu/p/11721116.html