进程锁(互斥锁)

进程锁(互斥锁)

【一】什么是进程同步(互斥锁)

  • 互斥锁(Mutex)是一种用于多线程编程中控制对共享资源访问的机制。
    • 其作用是保证在同一时刻只有一个线程在访问共享资源,从而避免多个线程同时读写数据造成的问题。
    • 互斥锁的基本原理是在对共享资源进行访问前加锁,使得其他线程无法访问该资源,当访问完成后再解锁,使得其他线程可以进行访问。
    • 通过这种方式,可以保证同一时间只有一个线程在执行关键代码段,从而保证了数据的安全性。
    • 需要注意的是,互斥锁会带来一些额外的开销,

【二】多个进程共享同一打印终端

  • 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,
  • 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理

【1】未加锁

  • 并发运行,效率高,但竞争同一打印终端,带来了打印错乱
# 并发运行,效率高,但竞争同一打印终端,带来了打印错乱
from multiprocessing import Process, Lock
import time
import os


def work(lock):
    lock.acquire()
    print(f'这是进程:>>>>{os.getpid()} 进程开始')
    time.sleep(2)
    print(f'这是进程 :>>>> {os.getpid()} 进程结束')
    # 走之后把锁放开
    lock.release()


if __name__ == '__main__':
    lock = Lock()
    for i in range(1, 5):
        process = Process(target=work,args=(lock,))
        process.start()
        
# 这是进程:>>>>15252 进程开始
# 这是进程 :>>>> 15252 进程结束
# 这是进程:>>>>34436 进程开始
# 这是进程 :>>>> 34436 进程结束
# 这是进程:>>>>39012 进程开始
# 这是进程 :>>>> 39012 进程结束
# 这是进程:>>>>19524 进程开始
# 这是进程 :>>>> 19524 进程结束
        
    # 总结 : 虽然加锁让我们的程序变成了串行,但是对于整个程序来说,安全
    # 以时间换空间

【2】多个进程共享同一个文件

import json
# 【一】什么是互斥锁
# 互斥锁(Mutex)是一种用于多进程编程中控制对共享资源访问的机制。
# 其作用是保证在同一时刻只有一个线程在访问共享资源,从而避免多个线程同时读写数据造成的问题。
# 互斥锁的基本原理是在对共享资源进行访问前加锁,使得其他线程无法访问该资源,当访问完成后再解锁,使得其他线程可以进行访问。
# 通过这种方式,可以保证同一时间只有一个线程在执行关键代码段,从而保证了数据的安全性。
# 需要注意的是,互斥锁会带来一些额外的开销,

from multiprocessing import Process, Lock
import time
import os

# 【二】多个进程共享同一打印终端
# 【1】未加锁
'''
def work(lock):
    # 进去之前 把门锁起来
    lock.acquire()
    print(f'这是进程 :>>>> {os.getpid()} 进程开始')
    # 模拟 IO 操作
    time.sleep(2)
    print(f'这是进程 :>>>> {os.getpid()} 进程结束')
    # 走之后把锁放开
    lock.release()


if __name__ == '__main__':
    # 声明一把锁
    lock = Lock()
    for i in range(1, 5):
        process = Process(target=work, args=(lock,))
        process.start()
    # 总结 : 虽然加锁让我们的程序变成了串行,但是对于整个程序来说,安全
    # 以时间换空间
'''
# 【三】多个进程共享同一个文件
'''
BASE_DIR = os.path.dirname(__file__)
file_name = 'data.json'
file_path = os.path.join(BASE_DIR, file_name)


# 【一】初始化票数
def save_data(data=None):
    if not data:
        data = {'ticket_number': 2}
    with open(file_path, mode='w') as fp:
        json.dump(data, fp)


# 【二】获取票数信息
def get_ticket_number():
    with open(file_path, 'r') as fp:
        data = json.load(fp)
    return data


# 【三】查看票数
def search_ticket_number(name):
    ticket_data = get_ticket_number()
    print(f'当前用户 {name} 正在查询余票 {ticket_data.get("ticket_number")} ')


# 【四】买票
def buy_ticket(name):
    # 获取票数信息
    ticket_data = get_ticket_number()
    ticket_number = ticket_data.get("ticket_number")
    # 模拟网络延迟
    time.sleep(2)

    # 【2】买票
    if ticket_number > 0:
        # 把票买走,减少库存
        ticket_data['ticket_number'] -= 1
        # 存到文件里
        save_data(data=ticket_data)
        print(f'当前用户 :>>>> {name} 购票成功!')
    else:
        print(f"当前用户 :>>>> {name} 已无余票!")


def main(name):
    # 【1】先让他查票
    search_ticket_number(name=name)
    # 【2】买票
    buy_ticket(name=name)


if __name__ == '__main__':
    save_data()
    task_list = []
    for i in range(1, 5):
        process_obj = Process(target=main, args=(i,))
        process_obj.start()
        task_list.append(process_obj)

    # join 等待
    for process_obj in task_list:
        process_obj.join()
'''

BASE_DIR = os.path.dirname(__file__)
file_name = 'data.json'
file_path = os.path.join(BASE_DIR, file_name)


# 【一】初始化票数
def save_data(data=None):
    if not data:
        data = {'ticket_number': 2}
    with open(file_path, mode='w') as fp:
        json.dump(data, fp)


# 【二】获取票数信息
def get_ticket_number():
    with open(file_path, 'r') as fp:
        data = json.load(fp)
    return data


# 【三】查看票数
def search_ticket_number(name):
    ticket_data = get_ticket_number()
    print(f'当前用户 {name} 正在查询余票 {ticket_data.get("ticket_number")} ')


# 【四】买票
def buy_ticket(name):
    # 获取票数信息
    ticket_data = get_ticket_number()
    ticket_number = ticket_data.get("ticket_number")
    # 模拟网络延迟
    time.sleep(2)

    # 【2】买票
    if ticket_number > 0:
        # 把票买走,减少库存
        ticket_data['ticket_number'] -= 1
        # 存到文件里
        save_data(data=ticket_data)
        print(f'当前用户 :>>>> {name} 购票成功!')
    else:
        print(f"当前用户 :>>>> {name} 已无余票!")


def main(name, lock):
    # 【1】先让他查票
    search_ticket_number(name=name)
    # 买票前加锁
    lock.acquire()
    # 【2】买票
    buy_ticket(name=name)
    # 买票后释放
    lock.release()


if __name__ == '__main__':
    save_data()
    lock = Lock()
    task_list = []
    for i in range(1, 5):
        process_obj = Process(target=main, args=(i, lock))
        process_obj.start()
        task_list.append(process_obj)

    # join 等待
    for process_obj in task_list:
        process_obj.join()
posted @ 2024-01-23 14:28  Fredette  阅读(815)  评论(0)    收藏  举报