进程锁

Posted whylinux

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进程锁相关的知识,希望对你有一定的参考价值。

# 进程锁
    # 多个进程都操作一个数据时(下面指的是文件或数据库)、会存在数据安全问题,则需要加入锁

# 先说一个现象
    # 买火车票
        # 当我们手机软件买票时,发现有余票20张,但是点击订票后,告诉你票订光了
        # 这是因为买票时,肯定是一个并发的过程,好多人同时来买票,并发的过程
        # 当一个人订票后,我们后台肯定要修改票数,肯定是修改数据库中的剩余票数

# import json
# import time
# from multiprocessing import Process
#
# def show():
#     ‘‘‘
#     @funcation功能:模拟查询余票
#                    显示余票
#     :return:
#     ‘‘‘
#     with open(‘ticket‘, mode=‘r‘) as f: # ticket文件中的内容是{"ticket":1}这个,模拟存储的票数
#         dic = json.load(f)
#     print(‘余票:%s‘ % dic[‘ticket‘])
#
# def buy_ticket(i):
#     ‘‘‘
#     @funcation功能:模拟买票
#     @param 表示谁来买票
#     :return:
#     ‘‘‘
#     with open(‘ticket‘) as f:
#         dic = json.load(f)
#         time.sleep(0.1) # 模拟网络延时
#
#     if dic[‘ticket‘] >= 1:   # 有余票
#         dic[‘ticket‘] -= 1  # 买一张票后,就减一张票
#         print(‘33[32m %d 买到票了33[0m‘ % i)
#     else:   # 没有余票了
#         print(‘33[31m %d 没买到票33[0m‘ % i)
#
#     time.sleep(0.1) # 模拟网络延时
#     with open(‘ticket‘, mode=‘w‘) as f:
#         json.dumps(dic, f)  # 将在内存中改写的余票数,写入到文件中,模拟写入数据库的过程
#
# if __name__ == ‘__main__‘:
#     # 创建5个进程,都绑定的查询余票为子进程,模拟5个人查票,此时5个人都看到有1张票
#     for i in range(5):
#         p = Process(target=show)
#         p.start()
#
#     # 5个人看到有1张票后,则都去点击买票,此时5个人都显示买到票了,也可能多个人显示买票成功了,这是有问题的,因为只有1一张票,确多个人显示买成功了
#     for i in range(5):
#         p = Process(target=buy_ticket, args=(i,))
#         p.start()


# 解决上面举的5个人查看余票都剩1张时,5个人都去点击买票,结果系统显示多个人买票成功的问题,可以用进程锁
    # 上面的问题由于操作文件的相关代码被多个人(进程)操作,
        # 如果多个进程同时都去读那个文件,就会同时读到剩一张票,点击买票时,同样的多个进程同时都去加载那个文件中的剩余票数,
        # 多个进程都发现有余票1张,所以多个进程就认为有余票,就买了,然后将票数减1后,多个进程又同时将余票数写入到了文件中
    # 解决上面的问题思路是,每个进程不能随便的就去读那个文件与写那个文件,而是需要拿到一个锁的钥匙后才能去操作那个文件,锁和钥匙只有一个
        # 当一个进程需要操作那个文件后,则拿到那个钥匙,开了锁后,进入到抽象中的屋子中,则用钥匙关闭了门,然后开始操作文件。
        # 此时如果有另一个进程也要进这个屋子的时候,则必须等待前面那个人操作完了文件后,将门打开并将钥匙归还,后面的人才能操作那个文件
        # 这就是进程锁的概念

import json
import time
from multiprocessing import Process
from multiprocessing import Lock    # 导入进程锁模块

def show():
    ‘‘‘
    @funcation功能:模拟查询余票
                   显示余票
    :return:
    ‘‘‘
    with open(ticket, mode=r) as f: # ticket文件中的内容是{"ticket":1}这个,模拟存储的票数
        dic = json.load(f)
    print(余票:%s % dic[ticket])

def buy_ticket(i, lock):
    ‘‘‘
    @funcation功能:模拟买票
    @:param 表示谁来买票
    @:param  接收锁对象的参数
    @:return:
    ‘‘‘
    lock.acquire()  # 如果钥匙被归还了,则拿到钥匙开锁向下执行,如果钥匙没有被归还,则阻塞在这里,等待锁被归还。  上锁
    with open(ticket) as f:
        dic = json.load(f)
        time.sleep(0.1) # 模拟网络延时

    if dic[ticket] > 0:   # 有余票
        dic[ticket] -= 1  # 买一张票后,就减一张票
        print(33[32m %s 买到票了33[0m % i)
    else:   # 没有余票了
        print(33[31m %s 没买到票33[0m % i)

    time.sleep(0.1) # 模拟网络延时
    with open(ticket, mode=w) as f:
        json.dump(dic, f)  # 将在内存中改写的余票数,写入到文件中,模拟写入数据库的过程
    lock.release()  # 归还钥匙      解锁

if __name__ == __main__:
    # 创建5个进程,都绑定的查询余票为子进程,模拟5个人查票,此时5个人都看到有1张票
    for i in range(5):
        p = Process(target=show)
        p.start()

    lock = Lock()   # 得到一个锁对象
    # 5个人看到有1张票后,则都去点击买票,此时每个进程都会先判断锁有没有被解开后再去买票,如果锁是上锁的则阻塞等待,先拿到钥匙的进程先买
    for i in range(5):
        p = Process(target=buy_ticket, args=(i, lock))  # 将锁传进去
        p.start()

 

以上是关于进程锁的主要内容,如果未能解决你的问题,请参考以下文章

Linux - 通过操作文件锁来实现shell script进程单实例

python多线程

忙等待中的互斥

在 Python 多处理进程中运行较慢的 OpenCV 代码片段

到底什么是分布式锁,进程锁,线程锁

java 简单的代码片段,展示如何将javaagent附加到运行JVM进程