美文网首页
并发编程-进程同步控制

并发编程-进程同步控制

作者: Yanl__ | 来源:发表于2019-10-23 11:26 被阅读0次

锁/信号量/事件

1.锁

2.信号量

3.事件

1.进程锁

# -*- coding: UTF-8 -*-

"""
# @Author  : yanlei
# @FileName: 进程锁.py

通过买票问题,来理解进程锁
"""
from multiprocessing import Process
import time
import json
from multiprocessing import Lock  # 导入进程锁

def query(i):
    with open('ticket') as f:
        dic = json.load(f)
    print('%s查询到余票还有 :%s 张'%(i, dic['ticket']))

def buy(i, lock):
    lock.acquire()  # 拿到锁  只有拿到锁的才能对数据库进行修改,数据库一次只能由一个对象进行修改
    with open('ticket') as f:
        dic = json.load(f)
    time.sleep(0.1)  # 模拟查询时的网络延迟
    if dic['ticket'] > 0:
        print('\033[0;31;0m %s买到票了\033[0m'%i)
        dic['ticket'] -= 1
    else:
        print('%s没有买到票'%i)
    time.sleep(0.1)
    with open('ticket', 'w') as f:
        json.dump(dic, f)

    lock.release()  # 归还锁


for i in range(10):
    p = Process(target=query, args=(i, ))  # 开启1买票0个查询线程,模拟并发
    p.start()

# 开启10个买票线程对一张票进行购买,模拟并发
lock = Lock()  # 先实例化一个锁的对象
for i in range(10):
    p = Process(target=buy, args=(i, lock))  # 将锁对象一并传递给buy
    p.start()
输出结果:
0查询到余票还有 :1 张
1查询到余票还有 :1 张
2查询到余票还有 :1 张
3查询到余票还有 :1 张
4查询到余票还有 :1 张
5查询到余票还有 :1 张
6查询到余票还有 :1 张
7查询到余票还有 :1 张
8查询到余票还有 :1 张
9查询到余票还有 :1 张
 0买到票了
1没有买到票
2没有买到票
3没有买到票
4没有买到票
5没有买到票
6没有买到票
7没有买到票
8没有买到票
9没有买到票
#加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。
虽然可以用文件共享数据实现进程间通信,但问题是:
1.效率低(共享数据基于文件,而文件是硬盘上的数据)
2.需要自己加锁处理

#因此我们最好找寻一种解决方案能够兼顾:1、效率高(多个进程共享一块内存的数据)2、帮我们处理好锁问题。这就是mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。
队列和管道都是将数据存放于内存中
队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,
我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性。

2.信号量

一次只能有指定的数量的进程来操作一套资源。 相当于加了N把锁,同时有N个进程都可以取钥匙、还钥匙。

# -*- coding: UTF-8 -*-

"""
# @Author  : yanlei
# @FileName: 信号量.py
"""
from multiprocessing import Process
from multiprocessing import Semaphore
import time
import random

def ktv(i, sem):
    sem.acquire()  # 获取钥匙
    print('%s进了ktv'%i)
    time.sleep(random.randint(1, 5))
    print('%s走出了ktv'%i)
    sem.release()  # 归还钥匙

sem = Semaphore(4)  # 一次只能有4个人使用这一套资源
for i in range(20):
    p = Process(target=ktv, args=(i, sem))
    p.start()

3.事件

e.is_set():查看当前是否为阻塞状态,False则为阻塞
e.wait():根据事件的状态决定自己是否在wait处阻塞。如果当前为阻塞,则一直等待
e.clear():将当前事件变成阻塞
e.set():将当前事件解除阻塞

from multiprocessing import Event

e = Event()  # 实例化一个事件对象
# 一个事件创建之后,默认是阻塞状态
print(e.is_set())  # e.is_set() 查看当前事件是否阻塞,False为阻塞状态
e.set()  # 将当前事件 解除阻塞
print(e.is_set())
e.clear()
print(e.is_set())
e.wait()  # 如果当前状态为阻塞,则会一直等待

红绿灯事件

from multiprocessing import Process, Event
import random, time

def traffic_light(e):
    while True:
        if not e.is_set():
            e.set()
            print('绿灯亮')
        else:
            e.clear()
            print('红灯亮')
        time.sleep(1)

def cars(e, i):
    if not e.is_set():
        print('%s号车在等红灯'%i)
        e.wait()
    print('%s号车通行'%i)

e = Event()
traffic = Process(target=traffic_light, args=(e, ))
traffic.start()
for i in range(20):
    car = Process(target=cars, args=(e, i))
    car.start()
    time.sleep(random.random())

相关文章

网友评论

      本文标题:并发编程-进程同步控制

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