并发编程 #2

文章目录

  • 一、进程锁
      • 前言
      • 1. 多进程抢占资源
      • 2. 加上进程锁
  • 二、如何查看进程号
  • 三、进程之间数据隔离问题
  • 四、队列(Queue)
        • 生产者消费者模型
  • 四、线程

一、进程锁

前言

锁在IT界都是非常重要的,不单单只有在Python中出现,尤其是数据库中的锁更多。比如:表锁、行锁、悲观锁、乐观锁、进程锁、互斥锁、递归锁、可重入锁、死锁、等···

1. 多进程抢占资源

当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题。

from multiprocessing import Process  # 导入进程模块
import time  # 导入时间模块


def index(i):  # 创建一个函数来作为子进程执行代码
    print(f'进程{i}进来了')
    time.sleep(1)
    print(f'进程{i}离开了')


if __name__ == '__main__':  # 进程必须在__name__ 中运行
    for i in range(5):   # 循环执行子进程5次
        p = Process(target=index, args=(i+1,))  # 实例化执行对象
        p.start()  # 开始执行进程


# 打印结果:
进程1进来了
进程2进来了
进程5进来了
进程3进来了
进程4进来了
进程2离开了进程1离开了

进程3离开了进程4离开了
进程5离开了

2. 加上进程锁

由并发变成了串行,牺牲了运行效率,但避免了竞争

from multiprocessing import Process, Lock  # 导入进程模块和进程锁模块
import time  # 导入时间模块


def index(i, lock):
    lock.acquire()  # 上锁
    print('进程%s进来' % i)
    time.sleep(1)
    print('进程%s离开' % i)
    lock.release()  # 解锁


if __name__ == '__main__':
    lock = Lock()
    for i in range(5):
        p = Process(target=index, args=(i + 1, lock))
        p.start()


打印结果
进程2进来
进程2离开
进程3进来
进程3离开
进程1进来
进程1离开
进程5进来
进程5离开
进程4进来
进程4离开

二、如何查看进程号

import time, os
from multiprocessing import Process


def index():
    print('index的子进程号:', os.getpid())
    print('查看index子进程的父进程号:', os.getppid())
    time.sleep(5)


if __name__ == "__main__":
    p = Process(target=index)
    p.start()
    print('查看子进程号:', p.pid)
    print('查看主进程号:', os.getpid())
    time.sleep(10)


打印结果:
查看子进程号: 11920
查看主进程号: 27780
index的子进程号: 11920
查看index子进程的父进程号: 27780

三、进程之间数据隔离问题

n=100

def task():
    global n
    n=1
    print("子进程")


from multiprocessing import Process

"""这两个进程之间的数据有没有通信? 么有通信"""
if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    """先让子进程先执行,让子进程去改值"""
    p.join()
    print("主进程中得值:", n)
    
"""问题是:如何让进程与进程之间数据通信? """

四、队列(Queue)

存储数据的地方,所有主进程和子进程都可以存数据或者取数据

from multiprocessing import Queue

q = Queue(3) # 括号内指定存储数据的个数,默认可以存SEM_VALUE_MAX =
#1. 往消息队列种存放数据
q.put(111)
print(q.full())  # 判断队列是否已满  False
q.put(222)
q.put(333)
print(q.full())  # 判断队列是否已满  True
#2.从消息队列取出数据
print(q.get())  # 111
print(q.empty())  # 判断队列是否为空  False
print(q.get())  # 222
print(q.get())  # 333
# print(q.empty())  # 判断队列是否为空  True
# print(q.get())  # 数据拿不到值,就会一直等着,处于阻塞态

print(q.get_nowait())  # 如果队列没有数据,会直接报错
"""full() empty()  在多进程种都不能使用,判断会出现失误,
执行q.full()是True,在极限情况,当队列满的时候,当一个进程执行q.get(),队列的数据会被拿走
执行q.empty()是true,在极限情况,队列是空的时候,你执行q.empty是空的下一秒有一个进程往里面存数据,此时的队列不是空的
,"""
生产者消费者模型
rom multiprocessing import Process, Queue


def product(q, bool):
    for i in range(10):
        q.put('这是我生产的%s个%s' % (i + 1, bool))


def consumer(q):
    while True:
        res = q.get()
        print(res)
        if res is None:
            break


if __name__ == '__main__':
    q = Queue(10)

    # 生产者
    p1 = Process(target=product, args=(q, '包子'))
    p2 = Process(target=product, args=(q, '饺子'))
    p3 = Process(target=product, args=(q, '馒头'))
    p4 = Process(target=product, args=(q, '鸡蛋'))


    # 消费者
    c = Process(target=consumer, args=(q,))
    c.start()

    p1.start()
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    p4.start()
    p4.join()
    q.put(None)

四、线程

在一个进程中,线程就是必须存在的,至少要有一个线程来执行任务
一个进程中可以有多个线程,在一个进程中可有开启多个线程来执行任务
进程和线程都是有操作系统调度的
进程是操作系统分配资源的基本单位,线程是操作系统执行的最小单位

如何开启线程? 跟开进程是一样的

import time
def task(a, b):
    print("from task")
    time.sleep(2)
    print("aaa")


from  multiprocessing import Process
from threading import Thread
import threading
if __name__ == '__main__':
    # p=Process(target=task)
    # p.start()
    # deamon
    """开线程的资源非常小,以至于代码走到这一行就立马开起来了,所以就会立刻执行"""
    t=Thread(target=task, name='Thread-2', args=('a', ), kwargs={'b':1})
    # t.setDaemon(True)
    """设置为了守护进程:主进程结束,子进程跟着结束"""
    t.daemon = True # 把该线程设置为守护线程, 主线程执行完毕,子线程也结束
    """守护线程有什么用?"""
    t.start()
    # t.join()
    # print(t.name)
    """一个进程中如果只有一个线程,该线程称之为是主线程,其他线程称之为是子线程"""
    t.is_alive()
    print(t.getName()) # t.name
    t.setName('aaaa')
    # t.name = 'aaa'
    print("主线程")
    print(threading.currentThread())
    print(threading.enumerate())
    print(threading.activeCount())

你可能感兴趣的:(网络,python)